You don’t need to look alike to be in the same type.

Union Quack.

When we are not amused by other peoples’ types.

Michel Belleville
Published in
3 min readDec 17, 2018

--

me> Wat.

wat> Say it one more time motherquacker! 🔫 🦆

me> Remember we talked about type alias that other time? In the end, we touched upon making your own types…

wat> Sure. Why would you want to make your own types then? Are existing types too good for you?

me> As a matter of fact, I’m not sure. I’m pretty happy with the types I know already. I have Bool for logic stuff, Int and Float to play with numbers, String to write, List when I want to have many things of the same type, tuples and records when I need to put some different things together…

wat> You do. But sometimes they’re not good enough. Say I want to represent votes for a simple yes or no question ; there are two possibilities: yes, and no. How would you represent your votes with the types you have?

me> Oh, that’s easy. I could have a Bool value that’s True for yes, and False for no!

wat> Ok, let’s do this with a type alias then:

type alias Vote = Bool

wat> But now there’s a problem because I want also to know when the vote hasn’t been cast yet…

me> Hmm… ok, that won’t work. Say I make it an Int and when it’s 1 it’s yes, and when it’s 2 it’s no and when it’s 0 it’s undecided…

wat> No points for clarity.

me> Hmm… yeah. Then a String is the obvious choice. I can say that "yes" is yes, and "no" is no and…

wat> …and "quack" is?

me> Not gonna happen? 😅 Ok, I see your point. A String can hold expressive values, but there’s no way to restrict what it holds to what I need.

wat> And it’s likely to force you to consider cases that should never bother you in the first place. So let’s give that Vote type its own, brand new shape:

type Vote
= Yes
| No
| Undecided

me> So, that’s a real type right? It doesn’t say alias.

wat> Indeed. And it’s what we can call a “union” type, because the possible values form some kind of set.

me> So a value of this type can be either Yes, No or Undecided, and nothing else? No weird, unaccounted values to deal with? No quack?

wat> No quack. Or maybe quack, if we decided to add it to the set of possible values. For example, say I not only want to account for undecided votes, but also for blank votes, and that those two notions are not the same:

type Vote
= Yes
| No
| Undecided
| Blank

me> Ok. So, how can I use this type?

wat> Say I want to give any vote a string representation ; "voted yes", "voted no", "still undecided" and "blank bulletin", I will need to know what the vote was to decide what string to return, like this:

voteToString : Vote -> String
voteToString vote =
case vote of
Yes ->
"voted yes"
No ->
"voted no"
Undecided ->
"still undecided"
Blank ->
"blank bulletin"
myVote : Vote
myVote = Yes
voteToString myVote
=> "voted yes"
voteToString Undecided
=> "still undecided"

me> So, this is saying in case vote is Yes, say "voted yes", in case it’s No, say "voted no"

wat> Yes. This is called pattern matching. It also works with other types too, like String, Int, List, …

me> Ok, so now I can make my own types with the values I need and only those. That’s cool. We’ll see about your pattern matching later if you will.

wat> But there is so much more to discover there…

me> Next time 😴

--

--