Skip to content

0008: Email Tutorials Haskell For Beginners ‐ Basics of Sum Types in Haskell

Bernard Sibanda edited this page Dec 9, 2025 · 2 revisions

LigerLearn Video 8

📑 Table of Contents

  • 8.1. From Product Types to Sum Types
  • 8.2. Sum Types and Union Types: The Big Idea
  • 8.3. Bool as the Simplest Sum Type
  • 8.4. Understanding the Bool Definition in Haskell
  • 8.5. Defining Your Own Sum Type: Month
  • 8.6. Enumeration Types and Nullary Constructors
  • 8.7. Why Sum Types Are Better Than Using Int
  • 8.8. Glossary of Terms for This Lesson

8.1. From Product Types to Sum Types

Earlier, you learned about product types, which combine several values together into a single structure, such as a custom Date type built from multiple components. In this lesson, you meet another fundamental concept in Haskell’s type system: sum types. While product types correspond to “and” combinations of values (this and that), sum types capture “or” relationships (this or that). Together, product and sum types give you powerful tools to model real-world concepts precisely in your code.

8.2. Sum Types and Union Types: The Big Idea

Sum types in Haskell are sometimes called union types, because they are conceptually similar to unions in set theory. Instead of saying “a value contains these components,” you say “a value can be one of these possibilities.” Technically, Haskell uses tagged union types, which means each possible form is clearly labeled so the compiler always knows which alternative you have. As a beginner, you do not need to worry about the detailed distinction between tagged and untagged unions. In this context, you can treat the terms sum type and union type as interchangeable.

8.3. Bool as the Simplest Sum Type

You have already used the Bool type in Haskell. When you declare a variable with type Bool, it can only take one of two values: True or False. There is no such thing as “half-true” or “partly false”; the type itself strictly limits the possible values. This is an important characteristic of sum types: the type enumerates exactly which values are valid. In the case of Bool, those values are True and False—nothing else.

8.4. Understanding the Bool Definition in Haskell

To see how sum types are written, the lesson shows the actual definition of Bool in Haskell. Conceptually, it looks like this:

data Bool = True | False

Let’s break this down:

  • data introduces a new type definition.
  • Bool is the name of the type.
  • = begins the list of constructors for this type.
  • True and False are the constructors, separated by a pipe symbol (|).

You can read the pipe symbol as “or,” so the whole definition reads naturally as:

“We are defining a data type called Bool, which has the constructors True or False.”

An important rule is that the type name (Bool) and all constructor names (True, False) start with a capital letter. The pipe (|) is the key piece of syntax for sum types: it separates the different alternatives that a value of the type may take. Bool is a sum type because the number of possible values is the sum of its constructors—in this case, two.

8.5. Defining Your Own Sum Type: Month

To solidify the idea, the lesson gives a small exercise: define a sum type Month that lists all months of the year, and then create some values of that type. The definition follows the same pattern as Bool:

data Month
  = January
  | February
  | March
  | ...
  deriving Show

Here:

  • Month is the type name.
  • January, February, March, and so on are the constructors, each representing one month.
  • The constructors are separated by the | symbol, meaning “January or February or March …”.
  • deriving Show is added so that values of type Month can be displayed in GHCi without errors.

To create values, you give them type Month and use the appropriate constructor:

jan :: Month
jan = January

feb :: Month
feb = February

These constructors do not take arguments; you simply choose which one you want when defining a value.

8.6. Enumeration Types and Nullary Constructors

The sum types shown so far—Bool and Month—are very simple:

  • Their constructors take no arguments.
  • Each constructor stands alone as one possible value.

Constructors that take no arguments are called nullary constructors. Data types like Bool and Month, whose constructors simply list all possible values in a fixed set, are often referred to as enumeration types (or enums). They “enumerate” every valid option for the concept you are modeling. For months, that list is finite and fixed, which fits enumeration perfectly.

8.7. Why Sum Types Are Better Than Using Int

You could try to represent months using an Int and agree informally that 1 means January, 2 means February, and so on. However, this is error-prone and less clear:

  • An Int can represent far more values than there are months (like 0, 13, 1000), which have no meaning as months.
  • A function taking an Int does not communicate that it expects a month; its intent is hidden.

By defining a custom sum type like Month, you achieve:

  • Clarity: type signatures involving Month clearly state that the values represent months.
  • Safety: you cannot accidentally pass 42 as a month, because the type system restricts you to constructors such as January, February, etc.

In other words, sum types let you encode your domain logic directly into the type system, making invalid states harder (or impossible) to represent.

8.8. Glossary of Terms for This Lesson

  • Sum type A type that can take one of several alternative forms, each represented by a constructor. The total number of possible values is the sum of the possibilities contributed by each constructor.

  • Union type Another name for a sum type, inspired by set unions. In Haskell, unions are tagged so the compiler always knows which alternative a value belongs to.

  • Tagged union A union type where each alternative has an associated tag (constructor name), making the alternative explicit and safe to inspect.

  • Constructor (data constructor) A named option in a sum type definition that creates values of that type. For Bool, True and False are data constructors.

  • Pipe symbol (|) The symbol used in Haskell type declarations to separate alternative constructors. It can be read as “or,” as in True | False.

  • Nullary constructor A constructor that takes no arguments. Examples include True, False, January, February, etc.

  • Enumeration type (enum) A sum type whose constructors simply list all possible values in a fixed, finite set, such as all months of the year or all days of the week.

  • Bool A built-in sum type with exactly two values: True or False. It is one of the simplest and most commonly used sum types.

  • Month (custom example) A user-defined sum type that enumerates all months. It demonstrates how to model a fixed set of meaningful values instead of using raw integers.

  • deriving Show A clause added to type declarations that instructs the compiler to automatically generate code for converting values of that type into strings, so they can be printed in GHCi.

Quizz & Progress Badge NFT

Clone this wiki locally