4

我只是在研究现实世界 Haskell 中的 monad 转换器。书上说,要使某个东西成为 monad 转换器,您需要使其成为 MonadTrans 类型类的实例。

于是书中定义了一个新的Transformer,即MaybeT m atransformer。

他们为这个新的转换器定义了 monadTrans 类型类:

instance MonadTrans MaybeT where
  lift m = MaybeT (Just `liftM` m)

然后他们为这个转换器创建了一个 MonadState 实例:

instance (MonadState s m) => MonadState s (MaybeT m) where
  get = lift get
  put k = lift (put k)

据我了解,lift 函数正在获取底层 monad 并将其包装在正确的构造函数中。但是,我没有在 MonadState 类型类中得到 get 或 put 的实现,我希望能帮助我理解 lift 在这里实际做了什么。我还听说在 mtl 包中,由于类型类的定义方式,您可以拥有一堆带有 WriterT、StateT 等的 monad 转换器,但您可以使用 get、put、tell 等函数而无需实际进行任何提升。我想知道这是如何工作的,我强烈怀疑它与这些类型类有关,但我不确定?

4

1 回答 1

1

但您可以使用 get、put、tell 等函数,而无需实际进行任何提升

这是因为这些函数实际上是在类型类上定义的MonadState,而不是State类型。

class Monad m => MonadState s m | m -> s where
    get :: m s
    put :: s -> m ()

然后,两者StateStateT都成为该类的实例,这使得使用那些可能1

在您的示例中,如果我们知道内部 monadMaybeT m是 (fulfills) MonadState s,我们可以将整个外部 monad 视为MonadState s我们提升了针对内部 monad 的操作,以便它们适合外部 monad,这与lift.

用简单的英语来说,这听起来像“如果 MaybeT 转换器转换(包装)在某个类型m的有状态 ( MonadState) monad 的 monad 上s,则生成的类型也是该类型的有状态 monad ”。


1这实际上只是一个实例,因为State s a实际上实现为StateT s Identity a. 有关实施细节,请参阅来源

于 2016-09-22T12:25:11.443 回答