我读过(例如here和here)所有基础monad
(Mabye
,Error
,...)派生自相应的monad变换器
(MaybeT
,ErrorT
,...)使用标识monad Identity
。一个例子是:
type Maybe a = MaybeT Identity a
但那当然不会导致Maybe a
的构造函数。
在sources MaybeT
中定义为newtype MaybeT m a = MaybeT (m (Maybe a))
。
我错过了重要的事情吗?
如何使用相应的monad变换器和identitiy monad导出基础monad导致混凝土
可以匹配的构造函数?
答案 0 :(得分:3)
这里使用了不同的方法。
有时,基础monad Foo
是根据变换器FooT Identity
定义的。例如,Daniel Wagner指出,来自变压器包的State
。
其他时候,基础monad Foo
是独立定义的。在这些情况下,Foo
和FooT Indentity
通常会发生不同类型,但同构。这意味着您可以在两种类型之间进行转换而不会丢失任何信息。
我想因为Maybe
在Haskell报告中定义为Prelude
类型,我们不能轻易地将其重新定义为同构MaybeT Identity
。实际上,由于通过与Maybe a
和Nothing
进行模式匹配来破坏/消除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操作(liftM
,runReaderT
等)。