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

时间:2017-09-07 15:05:12

标签: haskell monads monad-transformers

例如, Context 'State Progress returns 0' { mock Get-Status {return $true} -Verifiable $State = [PSCustomObject]@{Progress = 0} $result = Confirm-Session it 'should be' { $result | should be "Session for $Name not initiated. Retrying." } } 定义为:

MaybeT

但不是:

newtype MaybeT m a =
  MaybeT { runMaybeT :: m (Maybe a)}

为什么会这样?

2 个答案:

答案 0 :(得分:6)

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

要实施第一个join,您需要一种方法将Maybe分发到mdist1 :: Monad m => Maybe (m a) -> m (Maybe a)

join1 :: m (Maybe (m (Maybe a))) -> m (Maybe a)
join1 = fmap join . join . fmap dist1

要实施第二个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

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

dist1 :: Monad m => Maybe (m a) -> m (Maybe a) 
dist1 = sequenceA

dist2并不那么容易。对于任意Monad,无法做到这一点。作为一个反例,让我们选择m成为“读者”monad (->) r

dist2 :: (r -> Maybe a) -> Maybe (r -> a)

由于您无法访问r,因此dist2的唯一实施方案是const Nothing,这显然不符合monad法律。

答案 1 :(得分:2)

查看StateT可能很有启发性:

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }

这里的状态既不是"内部"也"外部",但它的类型与它正在转换的monad交错,一些位在内部,一些在外部。确实

newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }

全部"外部"。所以它取决于它是什么变压器。可能有一些类别理论至少部分地解释了这种交错,我很想知道它(知识分子?)。

与适用的仿函数形成对比

newtype Compose f g a = Compose { getCompose :: f (g a) }

也是一个应用,因此总有一个明确的内部/外部"关系。您可以制作仅适用于StateT的{​​{1}},并按Compose (State s)找到其结构:

ApplicativeStateT s f a = s -> (s, f a)

事实上,如果你在右边作曲,还有另外一个:

ApplicativeStateT' s f a = f (s -> (s,a))

但是monad没有这样的规律性。