Alex
Alex

Reputation: 1684

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

What's a good way to convert List (Maybe a) to Maybe (List a) in Elm?

The logic is simple:

Example 1:

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

Example 2:

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

Can it be done easily with some of the built-in functions?

The best I came up with looks like this:

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

And what would be an appropriate name for this kind of function? As I was searching for an answer, I saw that there's a function called sequence in Haskell which seems to be doing something similar.

Upvotes: 10

Views: 1994

Answers (2)

Igor Drozdov
Igor Drozdov

Reputation: 15045

@Chad Gilbert's answer sure is correct, but if you're looking for a simpler implementation of such a function, then the following line will do the trick:

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

Or just:

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

Maybe.map2 just takes a function and two Maybe values and applies the function to the values:

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

Note, that (::) function (prepend to the list) is used instead of (++) or List.append because it's more performant for the lists. Then foldr must be used instead of foldl to retain the order.

Upvotes: 6

Chad Gilbert
Chad Gilbert

Reputation: 36385

You can use the Elm Fancy Search tool and search on the function signature: List (Maybe a) -> Maybe (List a)

The first result turns up Maybe.Extra.combine

Upvotes: 10

Related Questions