There are concepts in Elm, as in other Functional Languages, that are simple, fun and elegant at the same time.
Two of them are the concepts of Result
and Maybe
. Elm is a language where The Billion Dollar Mistake has not being implemented. So, to deal with situation that can bring error, there are three types: Maybe, Result and Task.
All the following line can be executed in the elm Read-Eval-Print-Loop that, if you have Elm installed, you can activated running the command elm-repl
in the terminal.
If you don’t have elm installed, you can use an online version of elm-repl
at http://elmrepl.cuberoot.in/
Types definition
Let’s focus on Maybe and Result in this first part.
> type Maybe a = Nothing | Just a
> type Result error value = Err error | Ok value
You can also paste these type definition in elm-repl
but if you do so, you will overwrite the system definition and later you will get errors like
Function `withDefault` is expecting the 2nd argument to be: Maybe.Maybe numberBut it is: Repl.Maybe number
These two types are very similar. If you replace a
with value
:
> type Maybe value = Nothing | Just value
> type Result error value = Err error | Ok value
We get these similarities
Nothing <-> Err error
Just value <-> Ok value
Nothing
is the same as Error
without error
and Just
is the same as Ok
.
So the difference is that Result
has an extra string that describe the error (Err error
) while Maybe
just return Nothing
ignoring the error.
These are the signatures of the functions that are created defining the types.
> Ok
<function> : value -> Result.Result error value> Err
<function> : error -> Result.Result error value> Just
<function> : a -> Maybe.Maybe a> Nothing
Nothing : Maybe.Maybe a
Both Ok
and Err
are functions that accept a value as parameter and return a Result as output.
Just
and Nothing
return a Maybe
. Just
need a parameter but Nothing
is happier without it.
Two example of functions that returns Result and Maybe
These are two functions that we can use in our examples before that return a Maybe
(List.Head
) and a Result
(String.toInt
)
> List.head
<function> : List a -> Maybe.Maybe a> String.toInt
<function> : String -> Result.Result String Int
Now I will leave you with some simple example to execute in the console. All the following commands return “True : Bool” as result. If you want to learn more, refer to the excellent official doc:
- Result: https://guide.elm-lang.org/error_handling/result.html
- Maybe: https://guide.elm-lang.org/error_handling/maybe.html
Cases
> List.head [123] == Just 123> List.head [] == Nothing> String.toInt “123” == Ok 123> String.toInt “ABC” == Err “could not convert string ‘ABC’ to an Int”
Defaults
> Result.withDefault 0 (Ok 123) == 123> Result.withDefault 0 (Err “error”) == 0> Result.withDefault 0 (String.toInt “123”) == 123> Result.withDefault 0 (String.toInt “abc”) == 0> Maybe.withDefault 0 (Just 123) == 123> Maybe.withDefault 0 Nothing == 0> Maybe.withDefault 0 (List.head [123]) == 123> Maybe.withDefault 0 (List.head []) == 0
Conversion Result <-> Maybe
> Result.toMaybe (String.toInt “123”) == Just 123> Result.toMaybe (String.toInt “ABC”) == Nothing> Result.fromMaybe “error” (Just 123) == Ok 123> Result.fromMaybe “error” (Nothing) == Err “error”