MaybeT被定义为
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
而且,MaybeT m也是Monad类的一个实例,函数return
定义为
return = MaybeT . return . Just
但我读到了"It would also have been possible (though arguably less readable) to write return = MaybeT . return . return"
,这让我很困惑。
return = MaybeT . return . return
如何等于return = MaybeT . return . Just
?
答案 0 :(得分:7)
考虑MaybeT
的定义:
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
第一个return
定义(从下到上读取):
return =
MaybeT . -- put `m (Maybe a)` into `MaybeT`: MaybeT (m (Maybe a))
return . -- put `Maybe a` into external monad: m (Maybe a)
Just -- put value into `Maybe`: Maybe a
Maybe
也是一个单子。它的return
是Just
。这就是为什么第二个MaybeT
return
定义完全相同的功能的原因:
return =
MaybeT . -- put `m (Maybe a)` into `MaybeT`: MaybeT (m (Maybe a))
return . -- put `Maybe a` into external monad: m (Maybe a)
return -- it's the same as `Just` for `Maybe`: Maybe a
答案 1 :(得分:5)
在Haskell中,像return
这样的函数是多态的。如果你检查return
的类型,你会发现它是return :: Monad m => a -> m a
,表明它适用于任何monad。事实证明,Maybe
是一个monad,所以必须(标准库中的某个地方)instance
声明
instance Monad Maybe where
return = ...
...
并且,事实证明return
Maybe
的实例定义是
instance Monad Maybe where
return = Just
这表明我们允许用return
替换Just
的原因,但它并没有解释为什么Haskell实际上会这样做。
事实证明,Haskell使用类型推断来决定多态函数的“实际”类型。所以,要清楚,你的例子中发生的事情是Haskell能够识别最右边的return
必须返回Maybe
中包含的值,因此知道return
专门化return :: a -> Maybe a
1}}然后它使用instance Monad Maybe
的{{1}}定义并将其转换为return
。