Skip to content

0019: Email Tutorials Haskell For Beginners – Type Synonyms in Haskell

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

LigerLearn Video 19

📑 Table of Contents

  • 19.1. What Are Type Synonyms?
  • 19.2. How String Is Defined in Haskell
  • 19.3. Using Type Synonyms in Type Signatures
  • 19.4. Making Dates More Readable with Type Synonyms
  • 19.5. Readability vs. Type Safety
  • 19.6. When to Prefer Custom Types Instead
  • 19.7. (Bonus) Literate Haskell and .lhs Files
  • 19.8. Glossary of Terms

19.1. What Are Type Synonyms?

In everyday language, a synonym is a different word with the same meaning. A type synonym in Haskell works exactly the same way: it is another name for an existing type.

Type synonyms are created with the type keyword. They:

  • Do not create a new type
  • Only introduce a new name for an existing type
  • Help make type signatures clearer and more descriptive

They are a documentation and readability tool, not a new data structure.

19.2. How String Is Defined in Haskell

You’ve already been using a very common type synonym: String.

Under the hood, Haskell defines String like this:

type String = [Char]

This means:

  • String is just a synonym for a list of Char
  • Anywhere you see String, you can mentally replace it with [Char]
  • The compiler treats String and [Char] as exactly the same type

So the declaration can be read in plain English as:

“We are creating a type synonym called String, which is another name for a list of Char.”

19.3. Using Type Synonyms in Type Signatures

Once a type synonym is defined, you can use:

  • Either the original type, or
  • The synonym

interchangeably in type signatures.

For example, these two function signatures mean exactly the same thing:

-- Using the original type
greet :: [Char] -> [Char]

-- Using the synonym
greet :: String -> String

Both functions will be implemented and called in the same way. The synonym only affects how we humans read the code, not how the compiler stores it.

19.4. Making Dates More Readable with Type Synonyms

Suppose you represent a date as a triple of Ints:

(2025, 10, 31)  -- year, month, day (or is it day, month, year?)

By itself, the type (Int, Int, Int) does not tell you which number is the day, which is the month, and which is the year.

To improve readability, you can define type synonyms:

type Day   = Int
type Month = Int
type Year  = Int

Then you might define:

type Date = (Day, Month, Year)

Now, a type signature like this:

makeAppointment :: Date -> String

is much clearer to someone reading your code. It tells you that:

  • You expect a Date as input,
  • Under the hood this is just (Int, Int, Int),
  • But the intention—a calendar date—is now obvious.

Type synonyms therefore act like labels that make your function interfaces easier to understand.

19.5. Readability vs. Type Safety

Type synonyms do not change the underlying representation.

Even with:

type Day   = Int
type Month = Int
type Year  = Int
type Date  = (Day, Month, Year)

the compiler still only sees:

type Day   = Int
type Month = Int
type Year  = Int
type Date  = (Int, Int, Int)

This means:

  • You can still construct something like:

    badDate :: Date
    badDate = (31, 31, 2025)
  • This passes the type checker, because 31 :: Int is valid, and (Int, Int, Int) matches Date.

  • But logically, this is nonsense: there is no 31st month.

So:

  • Type synonyms help readability,

  • But they do not enforce correctness or prevent invalid combinations.

  • The compiler cannot distinguish between:

    (Year, Month, Day)
    (Day, Month, Year)
    (Month, Day, Year)

as long as they are all just (Int, Int, Int).

19.6. When to Prefer Custom Types Instead

To avoid the problems described above, a better approach is often to create custom types (e.g. with data or newtype) that:

  • More precisely represent your domain
  • Restrict the set of valid values
  • Make illegal states harder (or impossible) to represent

For dates, that might mean:

  • Defining dedicated types,
  • Validating the ranges for days and months,
  • Ensuring that you cannot accidentally swap positions or supply impossible values.

The key takeaway:

Use type synonyms when you want clearer, more descriptive type signatures, but rely on custom types when you need stronger guarantees about correctness.

19.7. (Bonus) Literate Haskell and .lhs Files

The transcript also briefly mentions literate programming and literate Haskell.

In literate Haskell:

  • Comments are the default, and
  • Code lines are explicitly marked.

A common style is:

  • Any line starting with > is treated as code,
  • All other lines are treated as comments or documentation.

For example, in a .lhs (literate Haskell) file:

This is a comment/explanation line.

> square x = x * x
> main = print (square 5)

Literate Haskell isn’t commonly used in everyday codebases, but:

  • It used to be popular for tutorials, papers, and explanatory code.
  • If you see files ending in .lhs, they may follow this style.
  • It fits the idea that code is embedded inside documentation, rather than documentation being added on top of code.

You don’t need to use literate Haskell as a beginner, but it’s useful to recognize it when you see it.

19.8. Glossary of Terms

  • Type synonym A new name for an existing type, created with the type keyword. It does not create a new type, only a new alias.

  • type keyword The keyword used to define a type synonym: type Name = ExistingType.

  • String A standard type synonym in Haskell for [Char] (a list of characters).

  • Tuple A fixed-size ordered collection of values, possibly of different types. For example, (Day, Month, Year).

  • Readability How easy it is for humans to understand code. Type synonyms mainly improve this.

  • Type safety The ability of the type system to catch incorrect or inconsistent uses of data at compile time. Type synonyms do not increase type safety on their own.

  • Custom type A type created using data or newtype that has its own constructors and can enforce structure and constraints more strongly than raw primitive types.

  • Literate Haskell (.lhs) A variant of Haskell source where the file is primarily documentation, and code is explicitly marked (often with > at the start of a line).

Quizz & Progress Badge NFT

Clone this wiki locally