【问题标题】:In a monad transformer, why is the known monad the inner one?在 monad 转换器中,为什么已知的 monad 是内部的?
【发布时间】:2017-09-07 15:05:11
【问题描述】:

例如MaybeT定义为:

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

但不是:

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

这是为什么?

【问题讨论】:

  • 因为我们转换了 Maybe monad,而不是 Maybe 包含的内容?
  • 我认为这个问题之前已经在某个地方得到了回答,但我找不到。

标签: haskell monads monad-transformers


【解决方案1】:

查看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,并通过Compose (State s) 找到它的结构:

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

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

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

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

【讨论】:

  • 我怀疑我们给一些变形金刚起的名字可能暗示了一种错误的模式。我们在State 之后命名StateT,在Reader 之后命名ReaderT,等等,这似乎暗示了某种一对一的关系。但是 monad 和 monad 转换器确实完全不同,自称是“正确”列表 monad 转换器的各种事物就证明了这一点。 “ListT done right”、pipes/conduit/streaming/machines/coroutines 和 LogicT(以及 LogicT 的无悔版本)似乎都对标题有合法要求。
【解决方案2】:

扩展新类型后,我们在第一种情况下有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,这显然不符合单子定律。

【讨论】:

  • 我认为直接关注join2 会更容易看出问题所在,而不是试图深入地推理它必须如何分解。我们可以对参数进行模式匹配,然后我们需要m (Maybe (m a)) -> Maybe (m a)。唯一不平凡的选择是Just,这导致m (Maybe (m a)) -> m a,闻起来像麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 2012-09-19
  • 2011-07-01
  • 2021-11-27
  • 2013-12-19
相关资源
最近更新 更多