直观了解单子的“运行”功能

时间:2019-02-05 13:27:06

标签: haskell functional-programming monads

我正在Haskell中学习有关monad的信息,我了解了为什么它们有用,我通常了解绑定,联接,返回的作用。

我还查看了基本阅读器/作者/状态/列表/​​可能还有单子的基本用法示例。

还是个初学者,我仍然不了解“运行”功能(例如runState,runReader,runWriter)的含义。它似乎没有像上面的函数那样的通用签名,如果它是可定义的/对所有单子都有意义,我就不会得到它。

1 个答案:

答案 0 :(得分:13)

大多数monad的run函数实际上只是内部表示monad的一种人工产物。例如,Reader单子理论上可以表示为公正

type Reader r a = r -> a

State

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

,依此类推。但是,如果这样做,我们将无法为MonadReader提供不同的类型类(包括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转换器,因此看起来有些复杂,但实际上它们仍在做相同的事情)。