【发布时间】:2011-09-29 15:21:29
【问题描述】:
一个令人困惑的问题的令人困惑的标题!我理解 a) monad,b) IO monad,c) Cont monad (Control.Monad.Cont),以及 d) ContT 延续转换器 monad。 (而且我对一般的 monad 转换器有模糊的了解——尽管不足以回答这个问题。)我了解如何编写一个程序,其中 所有 函数都在 Cont monad (Cont r a) 中,并且我了解如何编写一个程序,其中 所有 函数都在组合的 Cont/IO monad (ContT r IO a) 中。
但我想知道如何编写一个程序,其中 some 函数位于组合的 Cont/IO monad (ContT r IO a) 和 other 函数中Cont monad (Cont r a)。基本上,我想以延续风格编写整个程序,但只在必要时使用 IO monad(就像在“常规”Haskell 代码中一样,我只在必要时使用 IO monad)。
例如考虑这两个函数,以非延续样式:
foo :: Int -> IO Int
foo n = do
let x = n + 1
print x
return $ bar x
bar :: Int -> Int
bar m = m * 2
请注意,foo 需要 IO,但 bar 是纯的。现在我想出了如何完全使用 continuation monad 编写这段代码,但我还需要通过 bar 线程化 IO:
foo :: Int -> ContT r IO Int
foo n = do
let x = n + 1
liftIO $ print x
bar x
bar :: Int -> ContT r IO Int
bar m = return $ m * 2
我确实希望我的所有代码都采用延续样式,但我不希望必须在不需要它的函数上使用 IO monad。基本上,我希望这样定义bar:
bar :: Int -> Cont r Int
bar m = return $ m * 2
不幸的是,我找不到从 ContT r IO a monad 函数 (foo) 内部调用 Cont r a monad 函数 (bar) 的方法。有没有办法将未转换的单子“提升”为已转换的单子?即,如何更改foo 中的“bar x”行,以便它可以正确调用bar :: Int -> Cont r Int?
【问题讨论】:
标签: haskell monads continuations