为什么有些类型类以" Monad"为前缀?

时间:2015-05-30 13:49:49

标签: haskell monads

通过阅读一些代码,我有时会遇到以Monad为前缀的类型类,其中的示例包括MonadStateMonadIOMonadReader等。

这些目的究竟是什么?

MonadState为例,我知道

  • State允许无状态状态
  • StateT允许使用其他monad,例如IO"结合" 两者的功能

但是MonadState允许究竟是什么?

我不需要另外一组类似命名的类型/类型类,有人可以解释一下吗?

2 个答案:

答案 0 :(得分:7)

StateStateT以及其他类型来自transformers,而MonadState类型类和其他类型类似来自mtl。请注意,前者是 types ,而后者是类型

transformers中的类型是MonadMonadTrans的实例。你可以直接与他们合作,但有一些烦恼:

  • 如果您有多个深层的monad堆栈,则必须通过大量调用lift来填充代码,以便访问每个层的功能。

  • 有时两种不同的类型提供相同的"界面"。例如,RWSTReaderT都提供类似于读者的功能,例如ask。在编写函数时,必须承诺执行其中一个函数是很烦人的,因为它会降低一般性。

来自Monad*的{​​{1}}类型类可以缓解这些问题:

  • 他们有"传递"消除对mtl的许多调用的实例(或者更确切地说,自动处理它们)。例如,liftStateT的一个实例,但MonadState上的ReaderT也是StateT的一个实例,因此您可以使用MonadState直接。

    get
  • 您可以在功能中添加import Control.Monad import Control.Monad.Reader import Control.Monad.State -- put the environment in the state bar :: ReaderT Int (State Int) () bar = ask >>= lift . put -- we use lift here barMTL :: ReaderT Int (State Int) () -- This ONLY works if we have imported the -- required instances from mtl. -- The MonadState instance for ReaderT, in particular. barMTL = ask >>= put -- the put is auto-lifted 约束,并对Monad*"界面"而不是立即承诺monad的具体实现。通过这种方式,您的功能变得更加通用,并选择确切的"实现"被推迟到最后一刻。

    Monad*

答案 1 :(得分:2)

MonadState不是monad,而是Monad的子类。 State是monad(也是MonadState)。 monad子类MonadState用于使getput等函数适用于任何具有gettable / settable“state”概念的monad。