使用monad变换器和标识monad派生基monad

时间:2015-03-10 18:37:52

标签: haskell monads

我读过(例如herehere)所有基础monad (MabyeError,...)派生自相应的monad变换器 (MaybeTErrorT,...)使用标识monad Identity。一个例子是:

type Maybe a = MaybeT Identity a

但那当然不会导致Maybe a的构造函数。 在sources MaybeT中定义为newtype MaybeT m a = MaybeT (m (Maybe a))

我错过了重要的事情吗? 如何使用相应的monad变换器和identitiy monad导出基础monad导致混凝土
可以匹配的构造函数?

2 个答案:

答案 0 :(得分:3)

这里使用了不同的方法。

有时,基础monad Foo是根据变换器FooT Identity定义的。例如,Daniel Wagner指出,来自变压器包的State

其他时候,基础monad Foo是独立定义的。在这些情况下,FooFooT Indentity通常会发生不同类型,但同构。这意味着您可以在两种类型之间进行转换而不会丢失任何信息。

我想因为Maybe在Haskell报告中定义为Prelude类型,我们不能轻易地将其重新定义为同构MaybeT Identity。实际上,由于通过与Maybe aNothing进行模式匹配来破坏/消除Just _中的值是很常见的,因此我们无法使用其他定义。如果我们拥有用户可定义的模式,我们可以使用pattern Just x = Module.Just (Identity x),但我们没有这些(现在)。

相反,其他monad(例如State)不在Prelude中,也不在Haskell报告中。它们通常也不会通过导入Control.Monad.State的任何人通过模式匹配来破坏。在这种情况下,转移到StateT Identity变体的危害较小。

答案 1 :(得分:2)

Maybe monad未定义为MaybeT Identity a以实现向后兼容性,因为Maybe早在MaybeT之前就已成为GHC的一部分。

使用带有Identity的monad转换器不会导致可以匹配的类型构造函数,这是正确的。幸运的是,在使用monad变换器范例时,我从未对monad构造函数进行模式匹配。相反,您可以使用do表示法和monad操作(liftMrunReaderT等)。