我是Haskell的新手并且正在寻找一个函数的名称(或者通常是概念的名称):
该函数有两个参数:
1.元素列表[T]
2.一个接受T的函数,并返回一个Maybe U。
该功能的输出如下:
如果列表中的所有元素都映射到Some U,则返回Some [U]。
否则,返回None。
即。如果任何映射值为null,则返回null,否则只返回映射值。
答案 0 :(得分:12)
这是Traversable
类中定义的traverse
:
traverse :: Traversable t, Applicative f => (a -> f b) -> t a -> f (t b)
您的示例中的 t
是列表,f
是Maybe
,例如
traverse (\x -> if x < 5 then Just x else Nothing) [1,2,3]
> Just [1,2,3]
traverse (\x -> if x < 5 then Just x else Nothing) [1,2,3, 9]
> Nothing
答案 1 :(得分:5)
该功能名为traverse
,来自Data.Traversable
。
该类型最初可能会令人惊讶,因为它非常抽象:
traverse :: (Applicative f,Traversable t) => (a -> f b) -> t a -> f (t b)
Applicative
和Traversable
是两个接口(Haskell术语中的类型)。
我们想要执行的效果的Applicative
摘要。在您的情况下,它是失败的(Maybe
)但它也可能是失败原因(Either
),输入/输出(IO
),并发输入/输出({{3和其他许多人。
Traversable
对容器的类型进行抽象。在您的情况下,它是一个列表([]
)。但是其他容器也是Traversable
:有限容器,其形状独立于其自身的值。 Concurrently
和Trees就是例子。 (Maps 不是示例,因为它们的&#34;形状&#34;取决于它们的值:将所有元素更改为相同的值将减小集合的大小。)
Traversable
是支持&#34;内部迭代的容器的接口&#34;。它基本上是其他语言的forEach
。但它还为您提供了一个与原始形状相同的容器,它包含转换后的值。
如果您不关心转换后的容器,相关的Sets函数将丢弃结果,并仅针对效果执行。
mapM
函数是traverse
的同义词,由于历史原因而存在。
答案 2 :(得分:1)
虽然Data.Traverable.traverse
似乎是正确的答案,但您也可以自己实施类似的功能。
isJust :: Maybe a -> Bool
isJust (Just _) = True
isJust _ = False
withList :: (a -> Maybe b) -> [a] -> Maybe [b]
withList f xs | all isJust js = Just (map (\(Just x) -> x) js)
| otherwise = Nothing
where js = map f xs
*Main> withList (\xs -> if all (<10) xs then (Just (sum xs)) else Nothing) [[1,2,3],[4,5,6],[7,8,9]]
Just [6,15,24]
*Main> withList (\xs -> if all (<9) xs then (Just (sum xs)) else Nothing) [[1,2,3],[4,5,6],[7,8,9]]
Nothing