类似于catMaybes的Haskell函数,但其类型为[Maybe a] -> Maybe [a]。

5
我想要一个类型为以下的函数:
f :: [Maybe a] -> Maybe [a]

例如。
f [Just 3, Just 5] == Just [3, 5]
f [Just 3, Nothing] == Nothing
f [] == Just []

它类似于Data.Maybe中的catMaybes :: [Maybe a] -> [a],但是catMaybes会忽略Nothing,而我的f非常关注Nothing。我可以以一种简单的方式实现f(如下所示),但想知道是否有更惯用的方式(比如“应用函子”):
f :: [Maybe a] -> Maybe [a]
f xs = let ys = catMaybes xs
        in if length ys == length xs 
           then Just ys
           else Nothing

或者
f :: [Maybe a] -> Maybe [a]
f xs = if all isJust xs
        then catMaybes xs
        else Nothing

6
作为一个旁注启发法 -- 如果你正在编写一个典型的列表函数,并且发现自己使用了 length(特别是如果你使用了多次),那么你可能做错了某些事情。在 Haskell 中,它并不适用于大多数列表代码。这并非总是如此,但在学习过程中,你应该避免使用它。 :-) - shachaf
4
如果有疑问,使用 hoogle。我在 Hoogle 中搜索了 [Maybe a] -> Maybe [a] 并找到了正确答案 sequence。请参考。 - aaronlevin
1
我使用 hoogle 进行了搜索,发现了 catMaybessequence 是列表中的第一个结果。由于其类型不是 Maybe 而是 Monad,我忽略了它,并未意识到它们之间的联系。 - Causality
2个回答

21

你正在寻找的函数称为“sequence”:

sequence :: (Monad m) => [m a] -> m [a]

你可以使用Hoogle查找此函数:链接

示例:

>>> sequence [Just 3, Just 5]
Just [3,5]

>>> sequence [] :: Maybe [Int]
Just []
注意:在Data.Traversable中也有一个名为sequenceA的序列函数,它更加通用,但对于你的使用情况,来自Control.Monad的sequence函数已足够。

7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接