Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • return Just (List a) if all items are Just a
  • otherwise, return 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

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.

like image 264
Alex Avatar asked Oct 28 '18 13:10

Alex


Video Answer


2 Answers

@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.

like image 98
Igor Drozdov Avatar answered Sep 27 '22 17:09

Igor Drozdov


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

like image 27
Chad Gilbert Avatar answered Sep 27 '22 17:09

Chad Gilbert