I am trying to figure out if there is a way to avoid lots of case
statements while inserting records into the DB.
My current code sort of looks like this:
mt1 <- runDb $ do
muid <- insertUnique user
case muid of
Just uid -> do
let t1 = Table1 {..., user = uid}
maid <- insertUnique t1
case maid of
Just aid -> do
mo <- getBy $ UniqueField "somevalue"
case mo of
Just (Entity oid o) -> do
mcid <- insertUnique Table2 {..., oid = oid}
case mcid of
Just cid -> do
mfid <- insertUnique Table3 {..., cid = cid}
case mfid of
Just fid -> Just t1 -- original t1 that was created at the top of the chain
Nothing -> Nothing
Nothing -> Nothing
Nothing -> Nothing
Nothing -> Nothing
Nothing -> Nothing
Nothing -> Nothing
First of all, I have issues getting the code to compile but instead of trying to debug that, I wanted to see if there is a better way to do this.
At a conceptual level, I want to do something like below, where all the Maybe
values get unwrapped automatically to be used in subsequent invocations. If any point, we hit a Nothing
, I just want to return Nothing
. The whole code will run in a single transaction so if we hit a Nothing
in between, the transaction is rolled back
runDb $ do
uid <- insertUnique user
let t1 = Table1 {..., user = uid} -- uid is unwrapped to just the value
aid <- insertUnique t1
o <- getBy $ UniqueField "somevalue"
cid <- insertUnique Table2 {..., oid = oid}
fid <- insertUnique Table3 {..., cid = cid}
Just t1
I am Haskell beginner so I only have superficial understanding of Monads (I can use the simple ones fine) but when it comes to use it inside something like runDb
of Persistent, I have no idea how to put the pieces together.
Any suggestions on how I can simply the logic so I don't end up checking for failure each step of the way?
Update: Based on Michael's answer, I did something like this and it automatically unwraps the maybes when used.
mt1 <- runDb $ runMaybeT $ do
uid <- MaybeT $ insertUnique user
...
case mt1 of
Just t -> return t
Nothing -> lift $ left ...
Thanks!
The standard approach to something like this is the
MaybeT
monad transformer. Something like the following will probably work: