Haskell 在单子转换器中,为什么已知的单子是内部的?

Haskell 在单子转换器中,为什么已知的单子是内部的?,haskell,monads,monad-transformers,Haskell,Monads,Monad Transformers,例如,MaybeT被定义为: newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a)} 但不是: newtype MaybeT m a = MaybeT { runMaybeT :: Maybe (m a) } 这是为什么?在扩展新类型后,我们在第一种情况下有join::Monad m=>m(Maybe(Maybe(Maybe))->m(Maybe)(a),在第二种情况下有join::Monad m=>Maybe(Maybe(ma

例如,
MaybeT
被定义为:

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

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

这是为什么?

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

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

要实现第二个
join
您需要相反的分布规律
dist2::Monad m=>m(maybea)->maybea(ma)

dist1
易于实现(我将把monad transformer定律的证明留给您):

dist2
不是那么容易。不能对任意的
单子
执行此操作。作为反例,让我们选择
m
作为“阅读器”monad
(>)r

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

由于您无法访问
r
,因此将进行类型检查的
dist2
的唯一实现是
const Nothing
,这显然不符合monad定律。

查看
StateT
可能会有所启发:

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
在这里,状态既不是“内部”也不是“外部”,但它的类型与它正在转换的单子交错,有些位在内部,有些位在外部。而且确实

newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
都是“外部的”。所以这取决于它是什么变压器。可能有一些范畴理论至少部分解释了这种交错,我很想知道它(知识分子?)

与应用函子相比,应用函子

newtype Compose f g a = Compose { getCompose :: f (g a) }
也是一种应用程序,因此始终存在明确的“内部/外部”关系。您可以仅使应用程序成为
StateT
,并通过
Compose(states)
查找其结构:

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

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

但是单子没有这样的规律性。

因为我们变换的是
可能
单子,而不是
可能
包含的东西?我想这在以前的某个地方已经得到了回答,但我找不到它。我想直接关注
join2
更容易发现问题,而不是试图对它必须如何分解进行太深入的推理。我们可以对参数进行模式匹配,然后我们需要
m(Maybe(ma))->Maybe(ma)
。唯一不平凡的选择是
只是
,这会导致
m(可能是(ma))->ma
,闻起来有点麻烦。我怀疑我们给一些变压器起的名字可能暗示了一种错误的模式。我们在
State
之后命名
StateT
,在
Reader
之后命名
ReaderT
,等等,这似乎暗示了某种一对一的关系。但是单子和单子变形金刚确实有很大的不同,这可以从声称是“正确”单子变形金刚列表的各种事物中得到证明。“
ListT
done right”、管道/管道/流媒体/机器/协同程序和
LogicT
(以及
LogicT
的无悔反射版本)似乎都对该标题有合法的要求。
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
newtype Compose f g a = Compose { getCompose :: f (g a) }
ApplicativeStateT s f a = s -> (s, f a)
ApplicativeStateT' s f a = f (s -> (s,a))