有没有办法为嵌套monad实现bind?我想要的是以下签名:
(>>>=) :: (Monad m, Monad n) => m (n a) -> (a -> m (n b)) -> m (n b)
Run Code Online (Sandbox Code Playgroud)
它看起来应该是一项微不足道的任务,但我不知何故无法绕过它.在我的程序中,我将这种模式用于monad的几种不同组合,对于每种组合,我都可以实现它.但对于一般情况,我只是不明白.
编辑:似乎在一般情况下不可能.但在某些特殊情况下肯定是可能的.例如,如果内在的Monad是一个Maybe.因为我想要使用的所有Monads都可以使用,所以有额外的限制似乎对我来说很好.所以我稍微改变了一下这个问题:
我需要对n进行哪些额外限制,以便可以进行以下操作?
(>>>=) :: (Monad m, Monad n, ?? n) => m (n a) -> (a -> m (n b)) -> m (n b)
Run Code Online (Sandbox Code Playgroud)
扩展评论:如链接的 问题所示,有必要有一些功能n (m a) -> m (n a)甚至有机会使合成成为monad.
如果你的内部monad是a Traversable,那么sequence提供这样一个函数,以下将具有正确的类型:
(>>>=) :: (Monad m, Monad n, Traversable n) => m (n a) -> (a -> m (n b)) -> m (n b)
m >>>= k = do
a <- m
b <- sequence (map k a)
return (join b)
Run Code Online (Sandbox Code Playgroud)
事实上,几个众所周知的变换器实际上是简单的newtype包装器,而不是相当于它的东西(虽然主要用模式匹配来定义事物而不是字面上使用内部monad' Monad和Traversable实例):
MaybeT 基于 MaybeExceptT 基于 EitherWriterT基于(,)((,)通常没有Monad定义它的实例,并 WriterT使用错误的元组顺序来使用它,如果它有 - 但在精神上它可能有).ListT基于[].噢,哎呦 ......最后一个实际上因为不是单子而臭名昭着,除非被提升的单子是"可交换的" - 否则,单子法应该相等的表达可以给出不同的效果顺序.我的预感是,这主要来自列表能够包含多个值,而不像其他可靠的工作示例.
因此,虽然上面的定义将被正确输入,但它仍然可以打破monad定律.
也作为一种事后,一种其它变压器是这样嵌套单子,但在一个完全不同的方式:ReaderT基于使用(->)作为外单子.
| 归档时间: |
|
| 查看次数: |
512 次 |
| 最近记录: |