将列表(可能是a类型)转换为Elm中的Maybe(列表a类型)

10
什么是将 List (Maybe a) 转换为 Maybe (List a) 的好方法?逻辑很简单:如果所有项都是 Just a,则返回 Just (List a),否则返回 Nothing
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 的函数似乎做了类似的事情。


谁给我负评了至少能解释一下为什么要这么做吗?否则的话我永远不会发现我的错误。 - Alex
当然,这个问题太宽泛了,因为它提出了多个模糊的问题,部分基于个人观点,并且更适合在[codereview.se]上进行。请参阅[ask]和[help/on-topic]以获取更多信息。 - glennsl
我理解你的观点,但是我不确定它是否更适合在代码审查中,因为我不想让任何人审核我的代码。但是我确实认为,如果您这样认为,那么我表达自己的方式可能有些问题。 - Alex
2个回答

9

看起来他们的实现方式和我的相似。 - Alex

6

@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来保留顺序。

谢谢,我不知道有性能差异。而且很好地使用了内置函数! - Alex

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