15/01/2023
8 min read
FP

Content:

A basic understanding of functional programming concepts




Introduction


Why you should at least have some knowledge of functional programing concepts ?

Simply because nowadays functional programming is everywhere.

Especially in Frontend (React, Angular, Redux, Rxjs),in Backend too even in Object Oriented Programing languages, for exemple Java 9 introduce the lambda expression and you will encounter code that use the Stream api.

Having some knowledge of this paradigm will help you a lot to understand these technologies and tools, you’ll avoid painful debugging session ,

you’ll shorten your code by switching to an imperative approach to a declarative one.

Let’s jump right into functional programming concepts and patterns.


Referential transparency and the importance of using as many pure functions as you can


Don’t be afraid of this fancy term it simply mean than given the same inputs your function should always have the same output.

That means that your function should not mutate an its parameters or a variable outside of its scope neither perform some kind of I/O operations , this kind of function are called pure function a function that produce no side effects.

I’ll show you with some code exemples written in Typescript.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const add = (a:number,b:number) => a + b; // pure function let result = 6; const inpureAdd = (a: number) => { result += a; }; //inpure function const fetchTodos = async () => { try { const res = fetch("/todos"); const data = res.json(); return data } catch (err) { throw new Error(err.message); } };//impure function


You should prioritize pure functions because it will save you from the nasty bug of mutate a variable that is used somewhere else in your application.

For exemple one function mutate a variable that contains an array , and another function of your application also uses this variable but is expecting to use this variable with the state of this last before the mutation,

that kind of bug is really hard to find and you’ll loose a lot of time in debugging session. Pure function are also really easy to test because you can predict its output.


Closure


Closure is an important concept of FP(Functional Programming) because it is the key to grasp the others patterns. This concept is true for every programming language that treats function as first class citizen.

It means that the language treats function like other variable and you can pass a function as an argument to other functions and that function can return other function.

So Closure is the fact that a function as access to all the variables and arguments of all of its parents functions even when the parents function as been executed.

It’s seems complicated but I’ll show you with some code.


1 2 3 4 5 const add = (a:number) => (b:number) => a + b; // This function return another function and the function returned has access to the parameter a of its parent function. add(1)(2) //3



In language like Javascript you use closure everyday even without recognizing it.


Currying


If you understand Closure you’ll understand Currying too because Currying leverage the Closure concept.

Currying is simply writing a function that returns another function.

The add function of the Closure exemple is a curried function but why is it useful to write functions with this weird syntax ?

Simply because it allows us to compose more specific function from more generic function. I’ll show you an exemple.


1 2 3 4 5 6 7 8 9 10 const add = (a:number) => (b:number) => a + b; const add = (a: number) => (b: number) => a + b; const add1 = add(1); const add2 = add(2); add1(2) // 3 add2(2) // 4


Thinking like this will make you write function that are more reusable thus will shorten your code.

Currying can also be used for dependency injection, I use it a lot for building middleware in Express js, let me show you an exemple.


1 2 3 4 5 6 export const buildArticlesMiddleware = (services: { articlesRepository: ArticlesRepository }) => (req: Request, res: Response, next: NextFunction) => { req.articlesService = Object.freeze(services); next(); };


With this technique you can pass a fake repository to your function in your test and in your index.ts pass the real repository and do some integration tests on your real repository in isolation.


Partial Application


Again if you understand Closure you understand Currying so you already understand Partial Application which is the process of applying a function to some of its arguments.

The partially apply function gets returned for later uses. Indeed you’ll already saw partial application in the first Currying exemple we partially applied the add function to create the add1 function and the add2 function.


1 2 3 4 5 6 7 8 const add = (a:number) => (b:number) => a + b; const add1 = add(1); // partial application of the add function const add2 = add(2); // partial application of the add function add1(2) // 3 add2(2) // 4


Recursion





This is similar to a loop but without a loop instead for the iteration you’ll call the function within itself or a parent function that call your function. To finish the looping process you’ll need a base case .

A base case is an if statement that tell the function to return its result when a desired condition is met.

Let’s see a basic exemple with a max function who has the goal of finding the max number in an array.


1 2 3 4 5 6 7 const max = (array: number[], maxNum = -Infinity): number => { if (array.length === 0) return maxNum; const newMax = array[0] > maxNum ? array[0] : maxNum; return max(array.slice(1), newMax); }; max([2,3,5,1,]) // 5


The max function check if the first element of the array is greater than the current one if it is it replace the old max number with the new one.

Then the function call itself with a copy of the array without the first element in it and the new max if it changed or the old max if it hadn’t.

Why using this technique instead of a loop ? First of all beware that there is programming languages where there is no loops so recursion is your only option.

Secondly recursion will result in much shorter code for some type of problems look at the Fibonacci sequence for exemple are when you’re working with graphs.

Lastly be aware that if your programming language does not support tail recursion  you’ll encounter a stack overflow if you’re not careful.


Pointfree Style Programming


Pointfree style programming in another functional programming pattern where the goal is to work at another level of abstraction by creating functions composed or piplined by others functions.

Let’s see a basic coding exemple when the goal is to have a list of the names of my friends that are near me.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // not Pointfree style type Friends { id: number; name: string; nearMe: boolean; } const getFriendNearMe = (friends:Friends) => friends.filter(({ nearMe }: Friends) => nearMe).map(({ name }) => name); // Pointfree style type Friends { id: number; name: string; nearMe: boolean; } const keepNearMe = (friends: Friends[]): Friends[] => friends.filter(({ nearMe }: Friends) => nearMe); const getNames = (arr: Friends[]): string[] => arr.map(({ name }) => name); const getFriendsNearMe = getNames(keepNearMe(friends));


Most of the time you'll use pipe or compose for PointFree style you can find it in every FP library or write these yourself.


1 2 3 4 5 6 7 const pipe = (...fns) => fns.reduce((result, f) => (...args) => f(result(...args))); const compose = (...fns) => fns.reduceRight((result, f) => (...args) => f(result(...args))); const getFriendsNearMe = pipe(keepNearMe,getNames); const getFriendsNearMe = compose(getNames,keepNearMe);


pipe will apply your function left to right and compose will do the opposite. Pointfree style in the FP world is considered to be a more readable and composable way to write your functions.

This pattern is used in Rxjs for exemple so you should have at least a basic understanding of it if you want to use this library.


Conclusion


You saw the most common pattens and concepts in FP, I deliberately not talked about Category Theory, Functor and Monad because for a beginner in FP that would have not help you to understand the basics of FP.

If you want an oversimplified overview of what Functor and Monads are: Functor is a data structure who has a map method for example in JavaScript an Array is a Functor,

a Monad is a data structure who has a map method and flatMap method for exemple in Javascript an Array is a Functor but also a Monad,

a Promise is a kind of Monad too in Javascript because the then method that unwrapped the promise does the same thing that flatMap does.

I hope this article helped you to understand some of the most famous FP patterns and even if you did not understand all of it don’t worry with practice and patience you’ll get all of those.

I’ll leave you here with my favorites books on FP.


Books: