"run" 单子函数的直觉

Intuition for "run" function of monads

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

我还查看了基本 reader/writer/state/list/maybe monads 的基本用法示例。

不过,作为一个初学者,我仍然觉得我不了解 "run" 函数(例如 runState、runReader、runWriter)的一般含义。它似乎没有像上述函数那样的通用签名,如果它是可定义的/对所有 monad 都有意义,我不明白。

大多数 monad 的 run 函数实际上只是 monad 内部表示方式的产物;例如,Reader monad 理论上可以表示为

type Reader r a = r -> a

State 作为

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

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

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

instance Functor (Reader r)
  -- ....

instance Functor (State s)
  -- ...

我们的编译器会抱怨我们试图为 (->) a.

提供两种不同的 Functor 实现

所以我们只是用 newtype 或多或少地写了相同的东西而不是 type,例如

newtype Reader r a = Reader { runReader :: r -> a }

newtype State s a = State { runState :: s -> (s, a)}

如你所见,run 函数实际上并没有 任何事情,它们只是 "unwrap" 新类型所以我们可以得到底层值。

(实际实现可能涉及 monad 转换器,因此看起来有点复杂,但它们本质上仍在做同样的事情)。