A 2 minute read written by
One of the great advantages of Elm is its strong runtime guarantees, and one important technique
it uses to achieve this is using data types such as
Result to handle errors,
instead of having values like
undefined in the language.
These structures are very nice to work with, but if you don't know the tools
at your disposal, they can be tricky.
Suppose you have some data such as:
data : List String data = ["1", "17", "a87", "34", "3b7"]
This was supposed to be a list of integers, but for whatever reason whoever provided you with this data
also left in a bunch of garbage like
"a87". You're only interested in the strings that are valid integers,
and you also want to work with them as integers, not strings. Let's start writing our
We can convert strings to integers with the function
String.toInt : String -> Maybe Int
and we can use our old friend
List.map to apply the conversion to all the elements in the list:
List.map String.toInt data -- [Just 1, Just 17, Nothing, Just 34, Nothing]
Now we have our integers, wrapped in
Just, so all we have to do now is to remove the values that are
"I know this one! That's
List.filter, right?", you might have said prior to learning the lesson that
I am getting to in this post. Let's try.
List.filter isJust (List.map String.toInt data)
There are two problems with this solution:
First of all,
isJust is not provided by the core library.
We could get it from
elm-community/maybe-extra, or we could save ourselves a dependency
and just define it ourselves:
isJust maybe = case maybe of Just _ -> True Nothing -> False
Now we can see if it works:
List.filter isJust (List.map String.toInt data) -- [Just 1, Just 17, Just 34]
We got rid of the bad entries, but we have another problem.
All our values are still wrapped up in
Each time you would want to use these values, you would have to handle the case of it being
even though we just made sure all the
Nothing-values are gone.
We have now introduced an impossible state 💀.
What we really want is a function with the type
convert : List String -> List Int
as opposed to what we had, which was:
convert : List String -> List (Maybe Int)
Fortunately the solution is very simple! The core library provides the function which does exactly this:
List.filterMap : (a -> Maybe b) -> List a -> List b
List.filterMap takes a function that produces a
Maybe, and applies that functions to all the elements of a list
while unpacking the
Just-values, and removing the
Our final convert function can then be defined simply as:
convert = List.filterMap String.toInt convert data -- [1, 17, 34]
Error handling in Elm is easy as long as you you have the right functions in your tool belt.
List.filterMap and a few more you will be able to handle anything 🎉