Maybes in Elm

Priya Patil
4 min readMar 9, 2017

--

A Bit about Elm

Elm is a fun language to use and the basics are pretty beginner friendly. This is in part due to its active and open community and the fact that once you understand how the components are wired up it is also easy to get an app up and running relatively quickly.

Here is a link for some examples that the elm architecture tutorial provides and check out https://www.npmjs.com/package/create-elm-app if you’re interested in getting a default app up and running.

Elm is also a functional language which means that it does not hold on to state at any point and so is less prone to the errors that arise when there are mutable variables. It has lots of handy tools like elm-reactor that make it possible to have your code complied and running locally.

Maybe

An interesting feature in Elm is that of type Maybe. Maybe in Elm effectively encapsulates data that might or might not exist. This is pretty handy, especially if you are handling complex data that you do not have a lot of knowledge about or control over.

type Maybe a = Just a | Nothing

(a here is just a placeholder for a certain type like bool, String, Int etc.)

Something of type Maybe is always associated with Just or Nothing, as in it may be there or it may not be.

There is no concept of null or undefined in Elm and the introduction of Maybe forces you to think about handling cases where there might be nothing (eg. a value in an array that might not exist). It’s particularly useful for handling instances when there is the possibility of missing data.

An example of Maybe

List vegetarians = ["Ben", "Emily", "Alex"]List.head vegetarians = Just "Ben" : Maybe.Maybe String

If you were to remove the elements in the list and then try to access the head, this would be the result…

List.drop 3 vegetarians
|> List.head
Nothing : Maybe.Maybe String

…and if you were to act on something of type Maybe you would need a case statement to handle all eventualities.

type alias Person = {  name : String 
, dietaryRequirements : Maybe String
}
alex : Person
alex = { name = "Alex"
, dietaryRequirements = "no soy milk"
}
niamh : Person
niamh = { name = "Niamh"
, dietaryRequirements = Nothing
}
isVegetarian : Person -> Maybe String
isVegetarian person =

case person.dietaryRequirements of

Nothing ->
"no dietary requirements"

Just dietaryRequirements ->
person.dietaryRequirements

This would return Just “no soy milk” for Alex and Nothing “no dietary requirements” for Niamh and any other person who has no data under their dietary requirements (sadly this doesn’t cover the case of empty strings).

Maybe withDefault

withDefault is a handy convenience method that allows you to provide a default value for a Maybe type like so:

List somePartyPeople = [ben, alex, imran]List.drop 3 somePartyPeople
|> List.head
|> Maybe.withDefault Guest

Maybe …andThen

andThen is another hand little helper method that allows for chaining together like so. If Nothing is returned you can then chain another method that acts on the Maybe:

List guestList = [alex, samuel, issac, pete]type alias partyGuest = {  name : Maybe String
, drink : Maybe String}

imran : PartyGuest
imran = { name = "Imran"
, drink = "Mojito"}

checkOnList : Person -> Maybe String
checkOnList person =
if (List.any (\guest -> person.name == guest.name) guestList) then
Just Person
else
Nothing
addToList : List Person -> Maybe String
addToList guestList =
head guestList
|> andThen checkOnList

If head of guestList returns a Nothing the andThen will never execute, but if it returns a Just Person andThen will check the person is on the list.

There are also handy map functions that allow you to apply certain functions to elements in a list. The normal map function only applies the function to Just values in a list and returns Nothing if applied to a Nothing value.

map2, like the other map functions allows you to apply a function only if all the arguments are Just values, but does so for elements in two lists (and only for the elements that have a corresponding value in both lists), sort of like a zip function. map3, map4 and map5 also exist.

Maybe in Elm is pretty useful and makes handling data a little safer. This is a frequent problem when coding complex systems and is another reason why Elm is a pretty awesome language.

--

--