Monad 可以被解释为容器的形式:
- 列表:给定类型的项目聚合
- bag:无序聚合
- set:忽略多重性的无序聚合
- 也许:最多聚合一项
- 读取器 e:基数聚合 |e|
我想知道如何在这个 View 中以有意义的方式将延续解释为包/容器的形式。谢谢!
最佳答案
我喜欢将延续视为有漏洞的程序。我想我最初是从 Tekmo's blog 收集到这个见解的。 .
看看这个小延续:
import Control.Monad.Trans.Cont
program :: ContT () IO Char
program = ContT $ \doThing -> do
c <- getChar
doThing c
这是一个“缺少一个部分”的程序 - 即如何处理从 getChar
检索到的 Char
。我们可以通过用 putChar
之类的东西填充缺失的部分来运行它;通过 runContT 程序 putChar 计算延续将获得一个字符,然后将其打印到 stdout。
如果您习惯用抽象语法树表示程序,那么容器类比可能会很直观。
为了让它更清楚,您可以构建一个包含 DoThing
术语的小 AST,该术语表示需要填补的漏洞:
{-# LANGUAGE DeriveFunctor #-}
import Control.Monad.Free
data ExprF a =
GetChar (Char -> a)
| DoThing Char a
deriving Functor
type Expr = Free ExprF
getChar' :: Expr Char
getChar' = liftF (GetChar id)
doThing' :: Char -> Expr ()
doThing' c = liftF (DoThing c ())
program' :: Expr ()
program' = do
c <- getChar'
doThing' c
program'
希望更清楚地是一个容器;要运行它,我们需要以与任何其他递归容器类似的方式处理 AST:
eval :: Expr () -> (Char -> IO ()) -> IO ()
eval prog f = iterM alg prog where
alg (GetChar k) = getChar >>= k
alg (DoThing c k) = f c >> k
通过 eval program' putChar
评估 program'
类似于通过 runContT program putChar
运行 program
。
关于haskell - 延续作为有意义的理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32145000/