在没有明确检查成功的情况下链接数据库插入

时间:2015-06-28 04:12:42

标签: haskell monads persistent

我试图弄清楚在将记录插入数据库时​​是否有办法避免大量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 ... 

谢谢!

1 个答案:

答案 0 :(得分:6)

这种类似的标准方法是MaybeT monad transformer。以下内容可能会起作用:

runMaybeT $ do
    uid <- MaybeT $ insertUnique user
    ...