我需要一个将[Maybe a]列表作为输入,获取每个值,对其进行处理并返回Maybe [a]的函数。如果输入列表中没有内容,我想返回Nothing。
firstRequest.doOnSuccess(resp1 -> {
secondRequest.doOnSuccess(resp2 -> {
});
});
我写了这个
func [Just 1,Just 2,Just 3,Just 4,Just 5] => this returns Just [1,2,3,4,5]
func [Just 1,Nothing,Just 3,Just 4,Just 5] => this returns Nothing
它可以工作,但是我想知道是否可以做得更好。我不喜欢先做无mlist再重新映射mlist的部分。
答案 0 :(得分:7)
sequence :: Monad m => [m a] -> m [a]
函数已经存在此功能:
Prelude> import Control.Monad
Prelude Control.Monad> sequence [Just 3]
Just [3]
Prelude Control.Monad> sequence [Just 3, Nothing]
Nothing
Prelude Control.Monad> sequence [Just 3, Just 2]
Just [3,2]
Prelude Control.Monad> sequence [Just 1,Just 2,Just 3,Just 4,Just 5]
Just [1,2,3,4,5]
Prelude Control.Monad> sequence [Just 1,Nothing,Just 3,Just 4,Just 5]
Nothing
从本质上讲,这只是一个mapM id :: (Monad m, Traversable t) => t (m a) -> m (t a)
,因为对于一个3列表,它等于:
-- special case for 3 elements to demonstrate how it works
func3 [a, b, c] = do
ya <- a
yb <- b
yc <- c
return [ya, yb, yc]
或因此:
func3 [a, b, c] = a >>= \ya -> b >>= \yb -> c >>= yc -> return [ya, yb, yc]
(我在这里使用一种特殊情况,因为mapM
引入了一些额外的功能,使其更难理解)
自Maybe
起,Monad Maybe
的实现方式如下:
instance Monad Maybe where
return = Just
Nothing >>= _ = Nothing
(Just x) >>= f = f x
表示从元素(a
,b
或c
之一开始为Nothing
的那一刻起,结果就是Nothing
,如果所有值都是Just
,我们将使用lambda表达式“收集”这些值,并最终生成包含元素的列表。
您可以看到列表[]
作为Maybe
的概括(其中Nothing
是空列表,而Just
是单例列表),并且相同行为可以观察到:
Prelude Control.Monad> sequence [[1,2], [4,3]]
[[1,4],[1,3],[2,4],[2,3]]
Prelude Control.Monad> sequence [[1,2], [4,3], []]
[]
这里sequence
将产生一个叉积,但是如果提供我们要应用叉积的集合之一的元素的列表之一为空,则结果为也为空。