0

我对 Haskell 中的 monad 没有很好的把握,我不知道如何解决这个问题。

以下代码包含在 do 语句中。

(...)
x <- runDB $ do
    receipts <- selectList [] []
    users <- selectList [] []
    receiptUsers <- selectList [] []
    return $ joinTables3 receiptUserUserId receiptUserReceiptId receiptUsers users receipts
let allUsers = runDB $ do 
    receipts <- selectList [] []
    users <- selectList [] []
    receiptUsers <- selectList [] []
    return $ joinTables3 receiptUserUserId receiptUserReceiptId receiptUsers users receipts

let answer = functionUsingValue x --functionUsingValue allUsers
(...)

每个变量都不清楚它在这里是什么,但我希望这对我的问题来说不是问题。

我的目标是创建一个函数,它返回与 x 中存储的值完全相同的值,但我现在所拥有的不正确,而是该函数返回一个 monad。我怎么能做到这一点?

提前致谢。

4

1 回答 1

2

好吧,我做了一些挖掘,答案是……不。在 Yesod 的单子runDB中吐出一个结果。GHandler然而,这个 monad 实际上是几个 monad 的组合,包括IO.

在 Haskell 中,任何类型的函数IO a -> a都是非常不安全的,因为无法保证 monad 中发生的副作用何时或什至IO会运行!由于GHandler包含IO在那里,你不能运行它,这样做意味着你可以派生出这样的IO a -> a类型

uhoh :: IO a -> a
uhoh = runGHandler . liftIO

因此,如果您想x在纯代码中使用,要点是您编写纯代码

foo :: a -> b

然后你在你的代码中使用它

myHandler = do
  x <- runDB $ ...
  let x' = foo x
  saveTheWorldWith x'

但是你所有被你的单子“弄脏”的代码都必须保持在一起。正因为如此,通常您希望最小化“不纯”的代码,而是专注于编写纯函数并在不纯的计算中使用它们。

于 2013-10-30T23:25:11.210 回答