Mind-bending functional programming with TypeScript - part 1
Ed Bentley
Posted on April 8, 2020
- Part 1: Introduction
- Part 2: Effects
To start with, let's have a quiz.
Imagine a pure function, one with no side effects. You give it an input, it always produces the same output. It won't throw exceptions at you. It doesn't use variables outside the scope of the function. There's certainly no mutation.
We'll call it mysteryFunction
. Now the only thing I'll tell you is its type signature. You need to guess what the body of the function is.
Is that even possible? Let's try:
function mysteryFunction<T>(x: T): T
It takes an argument x
of generic type T
, and returns type T
.
Can you tell me, with absolute certainty, what's in the body of the function?
Try copying it into the TypeScript Playground and have a go:
function mysteryFunction<T>(x: T): T {
// ?
}
Scroll further to see the answer.
...
...
...
It's this:
function mysteryFunction<T>(x: T): T {
return x;
}
With just a type signature, we already know what the body of the function is. It just returns what you pass in. This is the only possible thing it could do (remember, it's pure - no console.log
or anything allowed). Nothing else. π€―
This function has a special name: the identity
function.
Now let's try again with this type signature:
function mysteryFunction(x: string[]): string
What's in the body of this function? Scroll further to see the answer.
...
...
...
No idea! π€·
It could return x[0]
, or x[1]
. It could just return a constant "lolz"
string. There are an infinite number of things it could be doing.
However since we know it's returning a string, we can guess some of the most likely things it's going to be doing.
Lastly, the opposite extreme of our first example: what's in the body of this function?
function mysteryFunction(x: any): any
...
...
...
It could literally be anything. But the space of possible things it could be is greater than our second mysteryFunction
(if we forget about practicalities like memory, we can say both have an infinite number of possible function bodies - but for any
it's a bigger infinity π€―).
What I'm saying is, the less we know about the types, the more we know about the function's body - no names required. As our types become more concrete we loose that intuition on what the function is doing.
Does this matter, you ask? Probably not a great deal for your day-to-day programming (saying that, keeping functions more generic does make them more reusable). But that's not the point of this series.
In this series we're going to explore some less mainstream but totally fascinating concepts from the land of functional programming. We'll be taking a look at topics such as Semigroups and Monads using the great fp-ts library by Giulio Canti.
I can't say what we'll look at is suitable for the majority of your programming. But throughout our journey we'll be expanding our minds and taking inspiration from novel concepts together.
Resources for this part:
- LambdaCast 9: Polymorphism And Abstraction
- A Type of Programming: introduction
- Infinity and its cardinalities
Next up is Part 2: Effects
Posted on April 8, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.