In Elm, Union Types are used for many things as they are incredibly flexible. A union type looks like:
type Answer = Yes | No
Answer can be either
No. Union types are useful for making our code more generic. For example a function that is declared like this:
respond : Answer -> String respond answer = ...
Can either take
No as the first argument e.g.
respond Yes is a valid call.
Union types are also commonly called tags in Elm.
Union types can have associated information with them:
type Answer = Yes | No | Other String
In this case, the tag
Other will have an associated string. You could call
respond like this:
respond (Other "Hello")
You need the parenthesis otherwise Elm will interpret this as passing two arguments to respond.
As constructor functions
Note how we add a payload to
This is just like a function call where
Other is the function. Union types behave just like functions. For example given a type:
type Answer = Message Int String
You will create a
Message tag by:
Message 1 "Hello"
You can do partial application just like any other function. These are commonly called
constructors because you can use this to construct complete types, i.e. use
Message as a function to construct
(Message 1 "Hello").
It is very common to 'nest' one union type in another.
type OtherAnswer = DontKnow | Perhaps | Undecided type Answer = Yes | No | Other OtherAnswer
Then you can pass this to our
respond function (which expect
Answer) like this:
respond (Other Perhaps)
It is also possible to use type variables or stand-ins:
type Answer a = Yes | No | Other a
This is an
Answer that can be used with different types, e.g. Int, String.
For example, respond could look like this:
respond : Answer Int -> String respond answer = ...
Here we are saying that the
a stand-in should be of type
Int by using the
Answer Int signature.
So later we will be able to call respond with:
respond (Other 123)
respond (Other "Hello") would fail because
respond expects an integer in place of
A common use
One typical use of union types is passing around values in our program where the value can be one of a known set of possible values.
For example, in a typical web application, we can trigger messages to perform actions, e.g. load users, add user, delete user, etc. Some of these messages would have a payload.
It is common to use union types for this:
type Msg = LoadUsers | AddUser | EditUser UserId ...
There is a lot more about Union types. If interested read more about this here.