在monad变换器中定义功能“返回”MaybeT

时间:2014-11-08 17:50:24

标签: haskell

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

2 个答案:

答案 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也是一个单子。它的returnJust。这就是为什么第二个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