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

时间:2018-01-29 21:22:03

标签: haskell monads monad-transformers

假设我想要一个用变量计算表达式的计算。我希望它在传递给它的运行器的env中看起来变量,并且还有某种状态和日志。我带了一个algebra,用RWS胡椒,我已经完成了。

lookup返回Maybe

所以我需要一个monad堆栈。

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

到目前为止一切顺利。但是这种类型有些混乱:变压器位于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更好,我怎样才能从Nothing获得EvalB

1 个答案:

答案 0 :(得分:3)

你需要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为基础,计算可能会失败,但仍会在日志中生成一个值。

一个非常好的练习是对ReaderWriterState中的每一个执行此操作,并找到可在MaybeT m,{mT Maybe之一中表示的计算{1}}但不是另一个。