我试图弄清楚在将记录插入数据库时是否有办法避免大量case
语句。
我目前的代码类似于:
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
首先,我在编译代码时遇到了问题,但我没有尝试调试代码,而是想知道是否有更好的方法来执行此操作。
在概念层面,我想做类似下面的事情,其中所有Maybe
值都会自动解包,以便在后续调用中使用。如果有任何意义,我们点击Nothing
,我只想返回Nothing
。整个代码将在单个事务中运行,因此如果我们在中间点击Nothing
,则事务将回滚
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
我是Haskell的初学者,所以我对Monads只有肤浅的理解(我可以使用简单的那些)但是当它在Persistent的runDb
之类的内容中使用它时,我不知道如何放置它拼凑在一起。
关于我如何简单地使用逻辑的任何建议,以便我不会在每一步都检查失败?
更新:根据迈克尔的回答,我做了类似的事情,并在使用时自动解开maybes。
mt1 <- runDb $ runMaybeT $ do
uid <- MaybeT $ insertUnique user
...
case mt1 of
Just t -> return t
Nothing -> lift $ left ...
谢谢!
答案 0 :(得分:6)
这种类似的标准方法是MaybeT
monad transformer。以下内容可能会起作用:
runMaybeT $ do
uid <- MaybeT $ insertUnique user
...