haskell - 延续作为有意义的理解

标签 haskell monads continuations

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/

相关文章:

haskell - 不确定如何使用组合器设计有用的库

Haskell 的 foldr/foldl 定义绊倒新手?对于 foldl 实际函数采用 f(默认情况)x 而对于 foldr 函数采用 f x(默认情况)?

list - Haskell 问题与空列表的潜在解决方法

scala - TailRec 和 State monad 的组成

Scala Continuations - 为什么我的转移调用不能位于 try-catch block 内?

haskell - 在haskell程序中使用返回的EitherT

haskell - 不使用序列实现mapM

f# - F# 中具有通用输出类型的免费 Monad

haskell - 我是不是写了续篇?

sml - 为什么 SML 中的以下延续函数不起作用?