gpt4 book ai didi

haskell - ask 函数如何知道要在 Reader monad 中返回的环境?

转载 作者:行者123 更新时间:2023-12-05 08:36:50 24 4
gpt4 key购买 nike

我正在 Reader monad 上阅读这个例子:https://blog.ssanj.net/posts/2014-09-23-A-Simple-Reader-Monad-Example.html有这个代码:

import Control.Monad.Reader

tom :: Reader String String
tom = do
env <- ask -- gives you the environment which in this case is a String
return (env ++ " This is Tom.")

我明白它的作用,但我不明白 ask 是如何返回任何东西的。

在 Haskell 中,函数可以作用于许多不同的类型。 ask 是一个没有输入并返回 monad 环境 m r 的函数。我试图了解当我这样做时会发生什么

(runReader tom) "Who is this?"

不知何故,runReader会调用tom,但是tom里面的ask怎么可能会是能够返回带有文本 Who is this??

env

最佳答案

Reader monad 中 do block 的每一行都会在后台发送环境的副本,就好像它已作为额外参数传入一样(感谢 Haskell 没有可变数据每个人得到相同的副本)。 ask 函数将其副本作为值返回。

ask 类型中的通用 m 替换为具体类型:ask::Reader r r 会有所帮助。这表示 ask 是一个 monadic Action ,其值(第二个 r)与环境(第一个 r)相同。为了使 ask 有用,必须存在 Reader r 上下文(这就是 do block 的用途)。在那个上下文中,r 总是坐在那里等待被使用。

想一想在没有 Monad 的情况下如何编写这个示例:

tom :: String -> String
tom env = env ++ " This is Tom."

jerry :: String -> String
jerry env = env ++ " This is Tom."

tomAndJerry :: String -> String
tomAndJerry env =
let
t = tom env
j = jerry env
in (t ++"\n"++j)

请注意 env 是如何手动传递给每个函数的? (顺便说一句,如果将 Reader raskrunReader 的定义替换到示例中,这正是您得到的结果。)The Reader monad 简单地为我们包装了收集和传递环境的过程,这很好,因为这是一个我们容易搞砸的过程(至少我是)。

当你有一个配置文件时,Reader Monads 真的很方便,你在启动时读取一次,然后在整个程序的其余部分引用。在命令式语言中,您可以将其设为全局常量变量。在 Haskell 中,你可以尝试将该值传递给每个需要它的函数,但是将它转储到 Reader monad 中更容易且更不容易出错(并且结果完全相同,只是没有所有的输入。)类型系统标记所有依赖于配置文件的函数的附带好处是,当配置格式更改时,编译器可以指出所有可能需要更新的地方。

关于haskell - ask 函数如何知道要在 Reader monad 中返回的环境?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67563852/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com