有没有办法为嵌套monad实现bind?我想要的是以下签名:
.factory('JMGoogleMaps', function ($cordovaGeolocation) {
var fac = {};
fac.users = ['John', 'James', 'Jake'];
return fac;
看起来它应该是一项微不足道的任务,但我不知何故不能绕过它。在我的程序中,我将这种模式用于monad的几种不同组合,对于每种组合,我都可以实现它。但对于一般情况,我只是不理解它。
编辑:在一般情况下似乎不可能。但在某些特殊情况下肯定是可能的。例如。如果内在的Monad是一个可能。因为我想要使用的所有Monads都可以使用,所以有额外的限制似乎对我来说很好。所以我稍微改变了一下这个问题:
我需要对n进行哪些额外限制,以便可以进行以下操作?
(>>>=) :: (Monad m, Monad n) => m (n a) -> (a -> m (n b)) -> m (n b)
答案 0 :(得分:7)
扩展评论:正如linked questions所示,有必要让某些函数n (m a) -> m (n a)
甚至有机会使合成成为monad。
如果您的内部monad是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)
几个众所周知的变换器实际上是简单的newtype包装器,而不是与此类似的东西(虽然主要是使用模式匹配来定义事物而不是使用内部monad'Monad
和Traversable
实例):< / p>
MaybeT
基于Maybe
ExceptT
基于Either
WriterT
基于(,)
((,)
通常没有定义Monad
个实例,和 WriterT
正在使用错误的元组命令,如果有的话,可以使用它 - 但在精神方面它可能有。)ListT
基于[]
。哦,哎呀 ...... 最后一个事实上是因为不是monad而臭名昭着,除非被提升的monad是“可交换的” - 否则,monad法则应该相等的表达可以给出不同的效果顺序。我的预感是,这主要来自于能够包含多个值的列表,这与其他可靠的工作示例不同。
所以,虽然上面的定义是正确的类型,但它仍然可以打破monad法则。
另外,作为事后的想法,另一个变换器是这样一个嵌套的monad,但是以完全不同的方式:ReaderT
,基于使用(->)
作为外部 monad。