Addendum

Types Composition

Creating new types

Algebraic data types do not support inheritance

  • They cannot inherit from a base class.

  • They are sealed: they cannot be inherited.

  • But they can implement interfaces.

Algebraic types are created by composition:

  • Aggregation into a product type (Record, Tuple)

  • "Choice" in a sum type (Union)

Combine 2 unions?

Consider the 2 unions below dealing with French-suited cards (♠ ♣ ♥ ♦):

type Black = Pike | Club
type Red = Heart | Tile

How do you combine them to create a union of Pike, Club, Heart or Tile?

By flattening unions, as in TypeScript ❌

type Color = Black | Red

→ It's not the expected result: Color is an enum-style union, with 2 cases Black and Red, totally disconnected from the Black and Red types!

By creating a brand new union ⚠️

type Color = Pike | Club | Hear | Tile
let pike = Pike

By composition ✅

type Color = Black of Black | Red of Red
let pike = Black Pike

→ The new union Color is composed based on the 2 previous types:

  • Black union is used as data for the Color.Black case

  • Red union is used as data for the Color.Red case

Note

It's common in F♯ to write union cases like Black of Black where the case name matches the case field type.

Union (FP) vs Object Hierarchy (OOP)

👉 A union can usually replace a small object hierarchy.

Explanations

Behaviors/operations implementation:

  • OO: virtual methods in separate classes

  • FP: functions relying on pattern matchings

    • exhaustivity

    • avoid duplication by grouping cases

    • improve readability by flattening split cases in a single match..with

FP vs OOP

How we reason about the code (at both design and reading time)

  • FP: by functions → how an operation is performed for the different cases

  • OO: by objects → how all operations are performed for a single case

Abstraction

  • Objects are more abstract than functions

  • Good abstraction is difficult to design

  • The more abstract a thing is, the more stable it should be

👉 FP is usually easier to write, to understand, to evolve

FP vs OOP: Open-Closed Principle

It's easier to extend what's open.

OO: open hierarchy, closed operations

  • Painful to add an operation: in all classes 😓

  • Easy to add a class in the hierarchy 👍

FP: open operations, closed cases

  • Easy to add an operation 👍

  • Painful to add a case: in all functions 😓

    • Still, it's usually easier in F♯: only 1 file to change

☝️ Notes:

  • Adding a class = new concept in the domain → always tricky ⚠️

  • Adding an operation = new behavior for the existing domain concepts

Last updated

Was this helpful?