首页 > 解决方案 > 对单子“运行”功能的直觉

问题描述

我正在学习 Haskell 中的 monad,我了解它们为什么有用,我大致了解 bind、join、return 的作用。

我还查看了基本读取器/写入器/状态/列表/​​可能是单子的基本用法示例。

尽管如此,作为一个初学者,我仍然不觉得我掌握了“运行”函数(例如 runState、runReader、runWriter)的一般含义。它似乎没有像上述函数那样的通用签名,如果它是可定义的/对所有单子都有意义,我就不明白了。

标签: haskellfunctional-programmingmonads

解决方案


大多数 monad的run函数实际上只是 monad 如何在内部表示的人工制品。例如,Reader单子理论上可以表示为

type Reader r a = r -> a

State作为

type State s a = s -> (s, a)

等等。但是,如果我们这样做了,那么我们就无法为 和 提供不同的类型类(包括Monad)实现ReaderState因为它们都只能由(->).

——也就是说,如果我们写

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 转换器,因此看起来有点复杂,但它们本质上仍然在做同样的事情)。


推荐阅读