haskell - 对单子“运行”功能的直觉
问题描述
我正在学习 Haskell 中的 monad,我了解它们为什么有用,我大致了解 bind、join、return 的作用。
我还查看了基本读取器/写入器/状态/列表/可能是单子的基本用法示例。
尽管如此,作为一个初学者,我仍然不觉得我掌握了“运行”函数(例如 runState、runReader、runWriter)的一般含义。它似乎没有像上述函数那样的通用签名,如果它是可定义的/对所有单子都有意义,我就不明白了。
解决方案
大多数 monad的run
函数实际上只是 monad 如何在内部表示的人工制品。例如,Reader
单子理论上可以表示为
type Reader r a = r -> a
State
作为
type State s a = s -> (s, a)
等等。但是,如果我们这样做了,那么我们就无法为 和 提供不同的类型类(包括Monad
)实现Reader
,State
因为它们都只能由(->)
.
——也就是说,如果我们写
instance Functor (Reader r)
-- ....
和
instance Functor (State s)
-- ...
我们的编译器会抱怨我们试图Functor
为(->) a
.
因此,type
我们不是或多或少地用 编写相同的东西newtype
,例如
newtype Reader r a = Reader { runReader :: r -> a }
或者
newtype State s a = State { runState :: s -> (s, a)}
正如你所看到的,这些run
函数实际上并没有做任何事情,它们只是“解开”新类型,这样我们就可以得到底层的值。
(实际的实现可能涉及 monad 转换器,因此看起来有点复杂,但它们本质上仍然在做同样的事情)。
推荐阅读
- python - 非递归脚本的递归问题 - 并行处理
- python - WebDriverException:消息:服务 chromedriver 意外退出。状态码是:127 with ChromeDriver and Selenium in Ubuntu
- c# - C# webAPI 限制路由
- php - 从网站上的 MYSQL 表中检查促销代码
- javascript - 从当前页面的响应中重新加载完整的 html 代码
- firebase - 如何检索 Firebase 实时数据库中所有子项的列表?
- c# - 从 C# 中的线程启动的线程不会引发未处理的期望参数
- python - Python plot 仅使用 x 的每个第 n 个元素来标记 x 轴
- javascript - 如果选中另一个具有相同 ID 的复选框,如何禁用复选框
- windows - 如果服务未运行,批处理文件以启动多服务