【发布时间】:2021-12-20 04:23:14
【问题描述】:
我一直想知道为什么 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
【问题讨论】:
-
您的意思是
where inner ma = ...而不是let? -
我在某个时候为此实施了an
Applicativeinstance,但甚至不确定它是否符合法律。 -
主要的问题是,归根结底,您必须对
m a类型执行bind/>>=。然而,您得到了一个返回类型MaybeOT (m b)的函数。当然,必须为m a上的bind提供一个返回m b的函数,无论b。您可以从MaybeOT (m b)获取Maybe (m a)。但接下来呢?外部 monad 的信息就是你所拥有的,它是实现 monadic 组合(转换器)所需的信息——但在这一步中你需要把它扔掉。 -
相反,对于
MaybeT,Maybe是内部单子。你绑定一次m (Maybe a)。在这里,您有机会检查Maybe的内部Nothing。在这种情况下,pure可以帮助您构建外部 monad。此外,您获得的函数返回MaybeT m b。您可以从中获得m (Maybe b)- 这正是您在m (Maybe a)上成功bind所需要的。因此,它运行良好。您已经使用了有关Maybe的信息以及它在实现中的确切含义,而不必将其丢弃。 -
注意到
MaybeOT面临的主要问题是您在需要m (Maybe a)的地方遇到了Maybe (m a)。 This is also the primary problem you face when implementingbindfor arbitrary nested monads。因此,需要单子变压器。有趣的是,traversable monads 能够交换外部和内部上下文 - 从而允许它们绕过所有这些。
标签: haskell monads monad-transformers