Chapter 7
Tips ⚠️️
- Use try.purescript.org to test out the code examples in this book.
- Whenever the example code starts with
module Main where, make sure to clear out the code editor on try.purescript.org before pasting new code in. This will help to avoid unncessary errors
Sum Types
At the beginning of this book, we talked about the two big categories of tools we have at our
disposal when writing programs: input and output. When we write code for a program, we're
working with a very primitive yet powerful form of input. We create variables to store our data,
yet the type of data we can store is restricted to text, numbers, and symbols. We've worked with
text via the String type and numbers via the Int and Number types, but now we move on by
taking a look at symbols. I want to apologize now because what I've been calling symbols is more
formally known as sum types (also ADTs, short for Algebraic Data Types).
What are sum types?
Sum Types are a bit different from the other types we've worked with so far. Unlike String or
Int, these types align more closely with real world concepts. For example, perhaps we want a
variable that stores the current day of the week, or the grade you got on your last math test; with
sum types, we can create these types easily. Let's try it out.
The "Days of the Week" type
module Main where
import Prelude
data DayOfTheWeek
= Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
| Sunday
-- Create a variable to store the current day of the week
currentDay :: DayOfTheWeek
currentDay = Sunday
Alright! We got some new syntax to look at. Let's break this down a bit.
We create new types using the keyword data, followed by the name of our type.
Warning: Type names always start with a capital letter. Like variables and functions, spaces
aren't allowed either.
Here's an example:
module Main where
import Prelude
data CoolType
data NotCoolType
This alone is valid syntax and creates the types CoolType and NotCoolType, but if we stop here,
what we've created is our own version of Void types - types with no values. To add values to our
types, we add an = after our type name followed by a list of values.
module Main where
import Prelude
data CoolType
= Cool
data NotCoolType
= UnCool
Both CoolType and NotCoolType now have one valid value. At this point we've moved from
creating our own version of Void to creating our own version of Unit! In order to move on to
more useful types, we need one more piece of syntax; the | character. The | character could be
read as the word "or"; we use it to give our types more than one value. Let's use it to give our
types a few more useful values.
module Main where
import Prelude
data CoolType
= Cool
| VeryCool
| SuperCool
data NotCoolType
= UnCool
| VeryUnCool
| AbsolutelyLame
| UnthinkablyLame
Finally, our types have become much more interesting now. Our type CoolType has three valid values
to choose from, and NotCoolType has four. With that explanation behind us, we should be able to
understand our original DayOfTheWeek example now:
module Main where
import Prelude
data DayOfTheWeek
= Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
| Sunday
-- Create a variable to store the current day of the week
currentDay :: DayOfTheWeek
currentDay = Sunday
As demonstrated above, to create a variable using that type, we give it a type declaration using the
types name. When we assign it a value, we use one of the values listed after the types = sign:
currentDay :: DayOfTheWeek -- Type declaration using the name we gave our type
currentDay = Wednesday -- Value from the list of values
bestDayEver :: DayOfTheWeek
bestDayEver = Friday
humpDay :: DayOfTheWeek
humpDay = Wednesday
Why go through the trouble?
We could use Strings or Ints to do this, but that would be making life hard on ourselves. For
example, we could implement our DayOfTheWeek type using Strings like this:
module Main where
import Prelude
currentDay :: String
currentDay = "Sunday"
-- This doesn't make sense
tomorrow :: String
tomorrow = "PlutoDay"
-- What..?
yesterday :: String
yesterday = "Yo yo yo!"
The problem is, nothing is preventing us from entering values that have nothing to do with the days
of the week. On the converse, if we use our official DayOfTheWeek type, the compiler protects us
from such silly errors:
module Main where
import Prelude
data DayOfTheWeek
= Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
| Sunday
-- Create a variable to store the current day of the week
currentDay :: DayOfTheWeek
currentDay = Sunday
-- This will cause an error: "Unknown type PlutoDay"
tomorrow :: DayOfTheWeek
tomorrow = PlutoDay
-- This will cause an error: "Can't match String with DayOfTheWeek
yesterday :: DayOfTheWeek
yesterday = "Yo yo yo!"
As you can see from the above examples, handling this manually using the primtive types would be taking on a lot of mental burden that the compiler would otherwise automatically take care of for us.
Summary
We can create our own types using the data keyword. The general syntax used to create types using
data is as follows:
data YourTypesName
= Value1
| Value2
-- And create a variable to use them like this:
someVariable :: YourTypesName
someVariable = Value1
Types created in this way are called sum types. We can use these types to create variables that run closely with real world concepts, such as days of the week, school grades, etc.
We haven't seen everything sum types have to offer just yet, but we'll visit that at a later time.
Self Practice
1. Create a data type to represent school grades and then create a variable giving yourself the best grade you remember getting on a Math test. (Or any other test if you really don't like math).
2. Create a data type for your top five desserts, then create a variable that stores your
favorite one. (Use spy to output your answer to the console for extra points!)
Answers
Question 1.
module Main where
import Prelude
data LetterGrade
= A
| B
| C
| D
| F
lastMathGrade :: LetterGrade
lastMathGrade = C -- Don't judge, it was a hard class :'(
Question 2.
module Main where
import Prelude
import Debug.Trace
data BestDessert
= Brownie
| CinnamonMuffin
| CinnamonDonut
| CheeseCake
| DanishPastry
favoriteDessert :: BestDessert
favoriteDessert = spy "My favorite dessert is" CinnamonMuffin -- The ones from costco man...