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

标签 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 (m (Maybe a))) -> m (Maybe a)在第一种情况下,join :: Monad m => Maybe (m (Maybe (m a))) -> Maybe (m a)在第二。

实现第一个join您需要一种分发方式Maybe超过 m : dist1 :: 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 更改器(mutator)定律留给你):
dist1 :: Monad m => Maybe (m a) -> m (Maybe a) 
dist1 = sequenceA
dist2不是那么容易。它不能用于任意 Monad .作为反例,我们选择 m成为“读者”monad (->) r :
dist2 :: (r -> Maybe a) -> Maybe (r -> a)

由于您无权访问 rdist2 的唯一实现那将是 const Nothing ,这显然不满足单子(monad)定律。

关于haskell - 在 monad 转换器中,为什么已知的 monad 是内部的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46099700/

相关文章:

scala - 为什么 scala @tailrec 不能用于 Option.flatMap?

haskell - mapMonadTrans::MonadTrans xT => (m a -> n b) -> xT m a -> xT n b

monads - 为什么在编写新的 Monad Transformers 时使用样板

haskell - 包含函数的数据类型的仿函数实例

scala - Scala 中的 Monad 变形金刚

haskell - 为什么此 Reflex 代码会导致 Dynamics 以相同的值无限期触发?

haskell - 运行相同的 haskell 应用程序需要不同的时间

c - 为什么一个配合函数可以更快地收敛到解决方案?

haskell - 如何在 haskell 中做到这一点? [x^0,x^1,x^2,x^3 ...]

haskell - 在变压器堆栈的底部插入 ErrorT