给定一个 Nothing,我如何构造 RWST env log state Maybe 值类型的值?

Given a Nothing, how do I construct values of type RWST env log state Maybe value?

假设我想要一个用变量计算表达式的计算。我希望它在传递给它的运行器的环境中查找变量,并且还有某种状态和日志。我拿了一个 ,用 RWS 调味,我就完成了。

除了lookup returns Maybe.

所以我需要一个 monad 堆栈。

λ type EvalA = MaybeT (RWS () () ()) ()
λ runRWS (runMaybeT (MaybeT (return (Just ())) :: EvalA )) () ()
(Just (),(),())
λ runRWS (runMaybeT (MaybeT (return Nothing) :: EvalA )) () ()
(Nothing,(),())

到目前为止一切顺利。但是类型有点乱:transformer on top of transformer on top of Identity。为什么不翻转这个。

λ type EvalB = RWST () () () Maybe ()
λ runRWST (return () :: EvalB) () ()
Just ((),(),())
λ runRWST (Nothing :: EvalB) () ()

<interactive>:12:10: error:
    • Couldn't match type ‘Maybe a0’ with ‘RWST () () () Maybe ()’
      Expected type: EvalB
        Actual type: Maybe a0
    ..........
λ -- ...?

且不说有Nothing加日志比单独有Nothing好,如何从EvalB得到Nothing

您需要 lift,这是 monad 转换器支持的基本操作。

ghci> runRWST (lift Nothing) () ()
Nothing

但也要小心进行这种交换。 Maybe 不与 RWS 通勤。事实上,它与它们中的任何一个都不通勤!例如:

WriterT w Maybe a
  ≃ Maybe (a, w)

但是

MaybeT (Writer w a)
  ≃ Writer w (Maybe a)
  ≃ (Maybe a, w)

在前者中,以 Maybe 作为基础 monad,Nothing 值会擦除作者的日志——你得到的只是失败。在后者中,以 Writer 作为基础,计算可能会失败,但仍会在日志中产生一个值。

一个很好的练习是对每个 Reader, Writer, and State 执行此操作,并找到可以用 MaybeT mmT Maybe 之一表示但不能用另一个表示的计算。