链接数据库插入而不明确检查是否成功
Chaining DB Insertions Without Explicitly Checking for Success
我想弄清楚是否有办法在将记录插入数据库时避免大量 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
,我只想returnNothing
。整个代码将 运行 在单个事务中,因此如果我们在两者之间点击 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
之类的东西中使用它时,我有不知道如何将各个部分放在一起。
关于如何简化逻辑以便我最终不会在每一步都检查失败的任何建议?
更新:根据 Michael 的回答,我做了类似的事情,它在使用时自动打开 maybes。
mt1 <- runDb $ runMaybeT $ do
uid <- MaybeT $ insertUnique user
...
case mt1 of
Just t -> return t
Nothing -> lift $ left ...
谢谢!
像这样的事情的标准方法是 MaybeT
monad transformer。像下面这样的东西可能会起作用:
runMaybeT $ do
uid <- MaybeT $ insertUnique user
...
我想弄清楚是否有办法在将记录插入数据库时避免大量 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
,我只想returnNothing
。整个代码将 运行 在单个事务中,因此如果我们在两者之间点击 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
之类的东西中使用它时,我有不知道如何将各个部分放在一起。
关于如何简化逻辑以便我最终不会在每一步都检查失败的任何建议?
更新:根据 Michael 的回答,我做了类似的事情,它在使用时自动打开 maybes。
mt1 <- runDb $ runMaybeT $ do
uid <- MaybeT $ insertUnique user
...
case mt1 of
Just t -> return t
Nothing -> lift $ left ...
谢谢!
像这样的事情的标准方法是 MaybeT
monad transformer。像下面这样的东西可能会起作用:
runMaybeT $ do
uid <- MaybeT $ insertUnique user
...