-
Notifications
You must be signed in to change notification settings - Fork 4
0019: Email Tutorials Haskell For Beginners – Type Synonyms in Haskell
- 19.1. What Are Type Synonyms?
- 19.2. How
StringIs 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
.lhsFiles - 19.8. Glossary of Terms
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.
You’ve already been using a very common type synonym: String.
Under the hood, Haskell defines String like this:
type String = [Char]This means:
-
Stringis just a synonym for a list ofChar - Anywhere you see
String, you can mentally replace it with[Char] - The compiler treats
Stringand[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 ofChar.”
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 -> StringBoth 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.
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 = IntThen you might define:
type Date = (Day, Month, Year)Now, a type signature like this:
makeAppointment :: Date -> Stringis much clearer to someone reading your code. It tells you that:
- You expect a
Dateas 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.
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 :: Intis valid, and(Int, Int, Int)matchesDate. -
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).
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.
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.
-
Type synonym A new name for an existing type, created with the
typekeyword. It does not create a new type, only a new alias. -
typekeyword The keyword used to define a type synonym:type Name = ExistingType. -
StringA 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
dataornewtypethat 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).
Bernard Sibanda is a global Technology Entrepreneur, Web3 and Software Consultant with a deep focus on Cardano Blockchain, Midnight and Community building.
Key Positions:
- Founder, CTO, Developer Advocate cohort #1, Fullstake Developer, Cardano Ambassador, Catalyst Project Manager, DREP-WIMS:
- Co-founder of ABL Tech and Cardano Africa Live
- EBU-certified Plutus Pioneer (Plutus/Haskell)
- Cohort #1 Plutus Pioneer Developer
- Catalyst Community Reviewer & Funded Projects Manager
-
DRep for WIMS-Cardano (ID:
drep1yguj8zu48n99pv70yl6ckzt9hdgjy8yjnlqs2uyzcpafnjgu4vkul) - Intersect Developer Advocate
- Intersect Committe Member 2025-2026
- Cardano Marketer,Promoter and blogger
- Cardano Open Source Contributor
- Cardano communities and events organizer and builder
- Cardano Ambassador for South Africa
Official links:
- Stablecoins Dex
- Coxygen Global Universities
- WIMS Cardano Global
- Cardano Africa Live
- WIMS Cardano Videos
- Cardano Smart Contract Videos
- Fullstack IT Consulting
Social links: