在monad变换器中,为什么已知的monad是内部的?

Ben*_*Ben 9 monads haskell monad-transformers

例如,MaybeT定义为:

newtype MaybeT m a =
  MaybeT { runMaybeT :: m (Maybe a)}
Run Code Online (Sandbox Code Playgroud)

但不是:

newtype MaybeT m a =
  MaybeT { runMaybeT :: Maybe (m a) }
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

Ben*_*son 7

扩展新类型后,我们join :: Monad m => m (Maybe (m (Maybe a))) -> m (Maybe a)在第一种情况下和join :: Monad m => Maybe (m (Maybe (m a))) -> Maybe (m a)第二种情况下都有.

为了实现第一join,你需要一种方法来分发Maybem:dist1 :: Monad m => Maybe (m a) -> m (Maybe a):

join1 :: m (Maybe (m (Maybe a))) -> m (Maybe a)
join1 = fmap join . join . fmap dist1
Run Code Online (Sandbox Code Playgroud)

要实现第二个,join你需要相反的分配法则dist2 :: Monad m => m (Maybe a) -> Maybe (m a)

join2 :: Maybe (m (Maybe (m a))) -> Maybe (m a)
join2 = fmap join . join . fmap dist2
Run Code Online (Sandbox Code Playgroud)

dist1 很容易实现(我将向你证明monad变压器法则):

dist1 :: Monad m => Maybe (m a) -> m (Maybe a) 
dist1 = sequenceA
Run Code Online (Sandbox Code Playgroud)

dist2不是那么容易.它不能用于任意Monad.作为一个反例,让我们选择m成为"读者"monad (->) r:

dist2 :: (r -> Maybe a) -> Maybe (r -> a)
Run Code Online (Sandbox Code Playgroud)

既然你没有访问权限r,那么唯一的实施dist2就是const Nothing,这显然不符合monad法则.