gpt4 book ai didi

haskell - Monad Transformer 内部结构顺序

转载 作者:行者123 更新时间:2023-12-04 14:46:53 25 4
gpt4 key购买 nike

我一直想知道为什么 Monad Transformers 有例如 m(Maybe(m(Maybe a))结构顺序和为什么不Maybe(m(Maybe( m a))) .我试图实现第二个,但我无法完成它可能是因为我对 Haskell 知识不足。
在所有 monad 转换器中,我们总是有这样的结构吗?
如果是,那为什么?
如果不是那么什么时候从另一个中选择一个?

newtype MaybeOT m a = MaybeOT {runMaybeOT :: Maybe (m  a) }
instance (Monad m) => Monad (MaybeOT m) where
return = pure
(MaybeOT mma) >>= f = MaybeOT $
case mma of
Nothing -> Nothing
(Just ma) -> inner ma where
inner ma = do
a <- ma
undefined

最佳答案

您基本上已经发现为什么 monad 转换器是向内的而不是向外的(尼特:我很确定我在这里没有使用正确的术语,但您明白我的意思 - 在这里随时纠正我)。将您所知道的 monad 放在 中要容易得多(简单 == 更少约束)。数据位置 (内部),而不是 容器位置 (外部)。直观地,您可以理解为什么 - 毕竟,一元性质需要 容器是一样的。你可以对数据做任何你想做的事情,但你不能在绑定(bind)期间改变容器的类型。
当然,通过实际尝试实现 absurd ,更容易实现这一切。这是关于什么的。您在实现 >>= 时会遇到的最后一步/bindMaybeOT这是-

m a >>= ??? . runMaybeOT . f
哪里, mMonad , m a :: m a , f :: a -> MaybeOT m a , 和 runMaybeOT :: MaybeOT m a -> Maybe (m a) (还有 ??? :: ??? ,呵呵)
现在,您必须获得容器类型为 m 的 monad成功绑定(bind) m a .但可惜,您无法获得 m aMaybe (m a) !当它是 Nothing 时会发生什么?您实现 monad 转换器的主要工具是有关 的知识。特定的 monad 你正在实现变压器。而你的知识告诉你这是 absurd 的。
相比之下,实现 >>= 的最后一步为 MaybeT进展顺利。为了完整起见,这里是 MaybeT ——
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
在这里,您将绑定(bind)类型 m (Maybe a) .在绑定(bind)期间,您必须返回类型 m b ,不管 b .你得到一个函数, f , 类型 a -> MaybeT m b ,您可以轻松获得 m (Maybe b)来自 MaybeT m b .
啊哈!现在您可以看到解决方案。您获得的函数返回与您绑定(bind)的那个相同的外部 monad。这正是您所需要的。在 MaybeOT的情况下,你被困在 monad 上 m , 带有一个不返回带有外部 monad 的值的函数 m !
这就是关键的实现——你得到的函数必须能够用相同的外部 monad 给你一个值。这就是为什么 MaybeT (以及其他转换器)将未知的 monad 保持在外面 - 因为当你实现 >>= 时为 MaybeT ,您知道构造该外部 monad 需要绑定(bind)函数。
至少在直觉上,注意到您在这里遇到的问题是有帮助的 - 与您在实现 monadic 组合时将面临的问题完全相同。即 >>=对于嵌套的 monad。 Monads don't compose !这就是为什么你需要 monad 转换器!
如果你分解这个问题,你会注意到如果你有一个可以交换 monad 的函数,得到 Maybe (m a)来自 m (Maybe a)反之亦然——一切都会好起来的。 Monad 可以组合,Monad Transformer 可以看起来像你喜欢的样子,事实上,Monad Transformer 基本上没有任何用处。这个细节被注意到 in the answer linked above .所有你需要的是-
swap :: (Monad m, Monad n) => m (n a) -> n (m a)
This exists .它们被称为可遍历的单子(monad),事实上,如果你仅仅添加 Traversable限制您的 Monad MaybeOT 的实现,你中了金——
instance (Traversable m, Monad m) => Monad (MaybeOT m) where
return = pure
MaybeOT Nothing >>= _ = MaybeOT Nothing
MaybeOT (Just ma) >>= f = MaybeOT $ sequence $ ma >>= sequence . runMaybeOT . f
我认为它是符合法律的,但我必须检查一下。
在另一个注意事项中,完全有可能使 MaybeOT符合适用的法律。毕竟,您在实现 Monad 时面临的问题在这里根本不存在。应用程序确实构成。
instance Applicative f => Applicative (MaybeT f) where
pure = MaybeT . pure . Just
MaybeT f <*> MaybeT a = MaybeT $ liftA2 (<*>) f a
(或者,也许更简单)
instance Applicative f => Applicative (MaybeT f) where
pure = MaybeT . pure . Just
MaybeT f <*> MaybeT a = MaybeT $ (<*>) <$> f <*> a
据我所知,这应该是符合法律的。

关于haskell - Monad Transformer 内部结构顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69864664/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com