在 Elm 中将 List (Maybe a) 转换为 Maybe (List a)

Converting List (Maybe a) to Maybe (List a) in Elm

在 Elm 中将 List (Maybe a) 转换为 Maybe (List a) 的好方法是什么?

逻辑很简单:

Example 1:

input:  [ Just 1, Just 2, Just 3 ]
output: Just [ 1, 2, 3 ]

Example 2:

input:  [ Just 1, Nothing, Just 3 ]
output: Nothing

可以通过一些内置函数轻松完成吗?

我想到的最好的是这样的:

listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList listOfMaybes =
    List.foldl
        (\maybeItem ->
            \maybeResultList ->
                case ( maybeItem, maybeResultList ) of
                    ( Just item, Just resultList ) ->
                        Just (List.append resultList [ item ])

                    ( _, _ ) ->
                        Nothing
        )
        (Just [])
        listOfMaybes

这种函数的合适名称是什么?当我在寻找答案时,我看到 Haskell 中有一个名为 sequence 的函数,它似乎在做类似的事情。

您可以使用 Elm Fancy Search 工具并搜索函数签名:List (Maybe a) -> Maybe (List a)

出现第一个结果Maybe.Extra.combine

@Chad Gilbert 的回答肯定是正确的,但如果您正在寻找此类功能的更简单实现,那么以下行就可以解决问题:

listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList listOfMaybes =
    List.foldr (Maybe.map2 (::)) (Just []) listOfMaybes

或者只是:

listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList = List.foldr (Maybe.map2 (::)) (Just [])

Maybe.map2 只接受一个函数和两个 Maybe 值并将该函数应用于值:

> Maybe.map2 (+) (Just 2) (Just 3)
Just 5 : Maybe.Maybe number
> Maybe.map2 (::) (Just 2) (Just [1])
Just [2,1] : Maybe.Maybe (List number)

请注意,使用 (::) 函数(添加到列表中)而不是 (++)List.append,因为它对列表的性能更高。然后必须使用 foldr 而不是 foldl 来保留顺序。