How I got into Functional Programming

Sandro Maglione

Sandro Maglione

Functional programming

For every language I try my first instinct is searching: "Functional programming in [language]"

My journey with functional started with Haskell, with these exact lines below:

inc n = n + 1
length :: [Integer] -> Integer length [] = 0
length (x:xs) = 1 + length xs

I (like most) knew mostly OOP at the time. This was a shock: "what's this mess!?" ๐Ÿคฏ

Now (mostly) everything is functional for me ๐Ÿ’๐Ÿผโ€โ™‚๏ธ

This is how I got here ๐Ÿ‘‡


Scheme (Racket) aka Lisp

I started with Lisp, specifically Racket (Scheme):

(lambda (x y) ; this is a comment
    (+ (* x x) (* y y)))

Completely different from anything I have seen before at the time ๐Ÿคจ

This language introduced me to some core ideas:

  • Every program is an expression: computation is based on evaluating expressions (no statements)
  • lambda functions (anonymous functions)
  • Recursion (specifically tail recursion)
  • Closures (higher order functions)
  • Meta-programming (macros)

I'll probably never use Racket for a production app: the real value was learning its core programming ideas

Haskell (purity)

Haskell is a pure functional language.

A pure functional language enforces immutability and no side effects

A new bag of ideas here as well:

  • Absence of side effects (purely functional computations) and how to deal with it (IO)
  • Currying
  • Type system
  • Pattern matching (everywhere)
  • Call-by-need (lazy evaluation)
  • Typeclasses

My focus was to understand why these features are useful ๐Ÿค”

This required exploring other languages to see how they deal with the same problems ๐Ÿ‘‡

There is more.

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.

Dart

I was interested in implementing functional ideas in dart.

Turns how OOP does not adapt too well into pure functional:

abstract class HKT<G, A> {
  const HKT();
}
 
mixin Functor<G, A> on HKT<G, A> {
  HKT<G, B> map<B>(B Function(A a) f);
}

Nonetheless, the main ideas still remain and work:

  • Managed side effects (IO, Task)
  • Errors as values (Either)
  • Immutability (map, fold)
  • Pattern matching (since dart 3 ๐ŸŽ‰)
  • Lambda functions

This is when I started using dartz, and then implemented the first version of fpdart

Typescript

Typescript is more "functional friendly":

  • More focus on functions than classes
  • Better type inference (especially function return types)
  • More powerful type system (generic types)

My first library was purify-ts:

  • Maybe (aka Option)
  • Either
  • Immutability
  • Currying

Kotlin

Over time most language started adding more functional features: Kotlin is no exception.

I used Arrow:

  • Coroutines (suspend) instead of IO
  • map, fold, zip
  • Option and Either

Kotlin and Dart share a similar OOP origin: the patterns used to achieve functional programming are similar as well

OCaml

Most recently I tried OCaml as well.

OCaml goes full into pattern matching. It looks more like Haskell:

let collect_digits dig str =
  let int_option = int_of_string_opt str in
  match dig, int_option with
  | Empty, None -> Empty
  | Empty, Some n -> Full (n, n)
  | Full (f, l), None -> Full (f, l)
  | Full (f, _), Some n -> Full (f, n)

At these point all the patterns start to repeat: immutability, no side effects, purity, lambda functions and more


Hopefully this gives you an idea of a typical "functional programming journey".

I encourage you to research more about the features and patterns that I mentioned to understand how you can benefit from these ideas.

Take a look also at Effect Systems: these are the next step ๐Ÿš€

See you next ๐Ÿ‘‹

Start here.

Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.