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 ๐คฉ
Timeless coding principles, practices, and tools that make a difference, regardless of your language or framework, delivered in your inbox every week.
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 offpdart
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
(akaOption
)Either
- Immutability
- Currying
Kotlin
Over time most language started adding more functional features: Kotlin is no exception.
I used Arrow:
- Coroutines (
suspend
) instead ofIO
map
,fold
,zip
Option
andEither
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 ๐