跳转到内容

Haskell/解决方案/Monad 变换器

来自维基教科书,开放的书籍,为开放的世界

← 返回 Monad 变换器

1.

liftM 可以用 Monad 方法 return(>>=) 来定义。这些方法不足以定义 lift,因为内部 monad 中的值如何与基本 monad 和变换器协同工作取决于变换器的类型。特别是,变换器所包装的类型的差异,如 变换器泛滥 部分所说明的那样,使得通用实现变得不可能。

2.

newtype IdentityT m a = IdentityT { runIdentityT :: m a }

instance Monad m => Monad (IdentityT m) where
    return x = IdentityT (return x)
    (IdentityT m) >>= k = IdentityT $ m >>= runIdentityT . k

instance MonadTrans (IdentityT m) where
    lift = IdentityT

实现变换器

[编辑 | 编辑源代码]

1.

state :: MonadState s m => (s -> (a, s)) -> m a
state f = do
    s <- get
    let (x, s') = f s
    put s'
    return x

2.

它们并不等价。将 runMaybeT 的类型专门化为与 MaybeT (State s) 一起使用,我们得到

-- runMaybeT :: MaybeT m a -> m (Maybe a)
MaybeT (State s) a -> State s (Maybe a)

runStateTStateT s Maybe 执行相同的操作,我们得到

-- runStateT :: StateT s m a -> s -> m (a, s)
StateT s Maybe a -> s -> Maybe (a, s)

在第一种情况下,我们得到一个返回 Maybe aState 计算。在第二种情况下,我们得到一个函数,该函数从类型为 s 的初始状态开始,可能会返回一个结果和一个新状态,也可能不返回,因为结果类型为 Maybe (a, s)。在 MaybeT (State s) 中的 Nothing 仅破坏返回的结果,而在 StateT s Maybe 中,它也会破坏最终状态。这种比较可以说明一些一般性的论述

  • 一般而言,monad 的堆叠顺序很重要。
  • 当组合的 monad 被解包时,内部 monad 的效果优先于基本 monad 的效果。
  • 错误处理层,例如 MaybeTExceptT,通常位于变换器堆栈的顶部,以便在发生错误时保留其他涉及的 monad 的效果。
华夏公益教科书