Functional

Summary of everything important
  • Functional Design Patterns .

    • Explains from the start what FP is.

    • Keywords:

      • Separation of data and behaviour.

      • Types are just a set of data, not classes.

      • {17:06 -> 20:13}

        • Excellent explanation of Total Functions .

        • The input and output types document the function.

          • Either create a special input type, or expand the output to be an Option .

          • Do not lie and simply have exceptions inside the function.

        • "Use static types for domain modelling and documentation"

          • "Sorry Closure and JavaScript, not allowed".

      • {40:54 -> 49:43}

        • Explanation of the "Pyramid of Doom" problem

        • Introduction to Monads .

        • Explains Binds  / Monadic Binds .

        • Applied to Error Handling and Async, usually.

        • "Railway Oriented Programming".

        • This stuff really seems very useful. It becomes very clear how to handle errors.

      • {49:44 -> 53:06}

        • Maps .

        • .map

        • "Lifting".

        • "World of options" and "world of normal values".

        • "Most wrapper generic types have a .map, use it!".

        • "Mappable types are Functors "; that's just mathematical jargon.

      • {53:07 -> }

        • Monoids .

        • "A pairwise operation has become an operation that works on lists".

  • The main concept is immutability.

    • As a consequence, functions end up being 'pure'.

      • They do not cause side effects.

      • They are deterministic (always return the same value for the same arguments).

  • You do not manipulate an object, but replace it with a new object produced from the previous object's data.

    • "Whenever there is a need to change a value, we create new objects based on the old one. This is important because immutability means you cannot directly modify an object's state; you create a new object with the changed values."

Possible problems
Monads
  • Chaining continuations.

  • Immutability :

    • Preference for:

      • tuples.

      • structs.

      • immutable objects.

  • Classes :

    • Using classes is not a common practice since FP emphasizes pure functions, immutability and composition rather than encapsulation and inheritance common in OOP. However, classes are not impossible or forbidden in FP. They can be used but normally in a way that does not contradict core FP principles.

    • Using classes immutably :

      // Class representing a 2D point
      class Point {
          constructor(public readonly x: number, public readonly y: number) {}
      
          // Method that returns a new Point with changed values (immutability)
          move(dx: number, dy: number): Point {
              return new Point(this.x + dx, this.y + dy);
          }
      }
      
      // Using the class immutably
      const p1 = new Point(0, 0);
      const p2 = p1.move(10, 5);
      
      console.log(p1); // Point { x: 0, y: 0 }
      console.log(p2); // Point { x: 10, y: 5 }
      
      • This is allowed because:

        • The Point  class is immutable due to readonly  properties.

        • The move  method does not change the original object's state but returns a new object  with modified values, respecting FP immutability.

    • Using classes to encapsulate functional behavior :

      • Without breaking pure functions:

        class Calculator {
            constructor(private readonly value: number) {}
        
            // Operations that return new instances, without altering original state
            add(x: number): Calculator {
                return new Calculator(this.value + x);
            }
        
            sub(x: number): Calculator {
                return new Calculator(this.value - x);
            }
        
            result(): number {
                return this.value;
            }
        }
        
        // Using the class functionally (immutability)
        const c1 = new Calculator(10);
        const c2 = c1.add(5); // Does not change c1
        const c3 = c2.sub(2); // Does not change c2
        
        console.log(c1.result()); // 10
        console.log(c2.result()); // 15
        console.log(c3.result()); // 13
        
        
      • Breaking purity (therefore not 100% functional):

        • The Calculator  class encapsulates behavior that performs calculations.

        • Immutability can be kept here because the class can be used as an immutable object (creating new values instead of modifying state).

        • Goes against pure functions:

          • The behavior of modifying the value internally goes against pure functions because add  mutates the object's state directly.

        class Calculator {
            private value: number;
        
            constructor(initial: number) {
                this.value = initial;
            }
        
            add(x: number): Calculator {
                this.value += x;
                return this; // allows chaining
            }
        
            sub(x: number): Calculator {
                this.value -= x;
                return this;
            }
        
            result(): number {
                return this.value;
            }
        }
        
        // Using the class for chained calculations
        const calc = new Calculator(10);
        const result = calc.add(5).sub(2).result();
        console.log(result); // 13
        

Concepts

  • First-class Functions

    • In functional languages, functions can be treated as values.

    • You can assign functions to variables, pass them as arguments, and return them as results.

  • Immutability

    • Data is treated as immutable, meaning it cannot be changed after creation.

    • Modifying data requires creating a new copy with the desired changes.

    • Only constants and functions using that constant as input are used.

    • Pure Functions

      • Purity {52:46 -> 1:03:07} .

      • A pure function is deterministic: for the same inputs it always produces the same outputs, without altering global state or producing side effects.

      • This makes reasoning about code and parallelization easier.

      • The function output should depend only on inputs.

        • Nice, cool.

  • Function Composition

    • Functions can be combined to form other functions, promoting modularity and code reuse.

  • Recursion instead of Loops

    • Since mutability is discouraged, loops like for  or while  are replaced by recursion.

  • Expressions, not Statements

    • Everything in functional languages is an expression that returns a value rather than a statement that changes state.