haskell - 帮助读者单子(monad)

标签 haskell monads

我是haskell的新手,我必须编写一个程序上下文感知,所以我想我可以使用Reader Monad来保持从文件中读取的上下文,我知道如何读取文件,将内容放在tuplesssomething的列表中[([Char],[Char])],但我不知道如何实现 Reader Monad,以便在不使用命令式样式的情况下使程序的所有组件都可以使用该环境,特别是我不知道如何设置和使用环境,据我了解,我应该将它作为参数提供给需要 runReader 函数 env 环境的所有函数,但我很困惑,有人可以给我一些指示或好的教程吗?提前致谢

最佳答案

使用任何“正常”单子(monad)的基本方案 [0] 几乎完全一样。本质上:

  • 使用 do 编写返回单子(monad)类型值的函数如果你愿意,可以使用符号,就像你写一个 IO功能类似于 main .
  • 为您正在使用的 monad 使用任何特定功能。
  • 使用标准规则相互调用这些函数:
  • 使用 <- 绑定(bind)来自同一个 monad 的值获取“内部”值,导致另一个值“运行”。
  • 使用 let 绑定(bind)任何其他值,使其独立于一元结构。
  • 使用特定单子(monad)的专门“运行”函数来评估单子(monad)计算并获得最终结果。

  • 这样做,monad 描述的额外功能的所有困惑细节(在这种情况下,传递一个额外的环境参数)都会自动处理。

    现在,通常的 Reader 操作是 asklocal :
  • ask是持有环境的一元值;在 do阻止您使用它,就像使用 getLine 之类的东西一样在 IO单子(monad)。
  • local在 Reader monad 中获取一个提供新环境和计算的函数,在由前者修改的环境中运行后者,然后获取结果并将其放入当前函数中。换句话说,它使用本地修改的环境运行子计算。

  • “运行”函数被创造性地命名为 runReader ,它只是在 Reader monad 和环境值中进行计算,使用后者运行前者,并在 monad 之外返回最终结果。

    例如,这里有一些函数在 Reader monad 中进行一些无意义的计算,其中环境是表示何时停止的“最大值”:
    import Control.Monad.Reader
    
    computeUpToMax :: (Int -> Int) -> Int -> Reader Int [Maybe Int]
    computeUpToMax f x = do 
        maxVal <- ask
        let y = f x
        if y > maxVal
            then return []
            else do zs <- local (subtract y) (computeUpToMax f y)
                    z <- frob y
                    return (z:zs)
    
    frob :: Int -> Reader Int (Maybe Int)
    frob y = do
        maxVal <- ask
        let z = maxVal - y
        if z == y 
            then return Nothing
            else return $ Just z
    

    要运行它,您将使用如下内容:
    > runReader (computeUpToMax (+ 1) 0) 9
    [Just 8, Just 6, Nothing]
    

    ...在哪里 9是初始环境。

    几乎完全相同的结构可以用于其他 monad,例如 State , Maybe , 或 [] ,尽管在后两种情况下,您通常只使用最终的一元结果值而不是使用“运行”函数。

    [0] : 正常意味着不涉及编译器魔法,最明显的“异常”单子(monad)当然是 IO .

    关于haskell - 帮助读者单子(monad),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3451546/

    相关文章:

    javascript - 也许是 JavaScript 中的 monad

    haskell - 难道 (Alternative f, Foldable f) => Monad f 吗?

    haskell - 在 Haskell 中合并多个案例

    haskell - Karplus-Strong Algo 中的递归反馈 - 箭头

    haskell - 开始使用 Haskell

    haskell - 为什么我不能仅使用 Functor/Applicative 约束来实现这些函数?

    haskell - VTY-UI需要IO。我能让这件事发生吗?

    c++ - 如何在 C++ 中使用 std::optional

    Haskell 编写 myLength

    c# - 编写一个 C# 版本的 Haskell 无限斐波那契数列函数