Functional Programming In JS — With Practical Examples (Part 1)

Functional Programming(FP) can change the way you program for the better. But it’s hard to learn and many posts and tutorials don’t go into details like Monads, Applicative and so on and don’t seem to use practical examples to help us use powerful FP techniques on a daily basis. That’s why I thought of writing a post to make it easier to use FP techniques.

Please Note: The emphasis in this blog is on WHY xyz feature is required than just WHAT xyz feature is.

In Part 1, you’ll learn Functional Programming basics, Currying, Pure Functions, “Fantasy-land” specs, “Functors”, “Monads”, “Maybe Monads” and “Either Monads” via couple of examples.

Functional Programming

Functional Programming is a style of writing programs by simply composing a set of functions.

Essentially, FP asks us to wrap virtually everything in functions, write lots of small reusable functions and simply call them one after the other to get the result like: (func1.func2.func3) or in a compose fashion, like: func1(func2(func3())).

But in order to actually write programs in this style, functions need to follow some rules and overcome some challenges like the ones mentioned below:

The FP Challenges:

If everything can be done by composing a set of functions..

  1. How can we handle if-else condition? (Hint: “Either” Monad)
  2. How can we handle Null Exceptions (Hint: “Maybe” Monad)?
  3. How to ensure functions are truly “reusable” and can be reused anywhere, (Hint: Pure functions, referential transparency)?
  4. How to ensure the data we pass to it is unchanged so that we can reuse the data elsewhere(Hint: Pure functions, immutability)?
  5. If a function is taking multiple values but chaining can only pass a single value, how can we still make it part of a chain (Hint:currying” and “higher-order functions”)?
  6. and more..<add your question here>.

The FP Solution:

In order to deal with all these challenges, fully Functional Programming languages like Haskell provides various tools and concepts from mathematics like “Monads”, “Functors” and so on out-of-the-box.

While JavaScript doesn’t provide many of the tools out-of-the-box, thankfully it has enough FP features that allows people to write libraries.

Fantasy-Land Specs And FP Libraries

Libraries that want to provide features like Functors, Monads and so on, need to implement functions/classes that follow some specs in order to provide functionalities like they are in languages like Haskell.

Fantasyland specs is one of the prominent specs that explains how each JS functions/classes should behave.

The above picture shows all the specs and their dependencies. Specs are essentially laws and similar to “interfaces” in Java. From JS perspective, you can think of specs as “classes” or constructor functions that implement some methods like (map, of, chain and so on) according to the specification.

For example:

A JS class is a “Functor” if it implements a “map” method. And that map method must work as per spec (ps:This is simplified version and there are more rules).

Similarly, a JS class is an “Apply Functor” if it implements “map” and “ap” functions as per spec.

Similarly, a JS class is a “Monad” (aka Monad Functor), if implements requirements of “Functor”, “Apply”, “Applicative”, “Chain” and “Monad” itself (because of the dependency chain).

Note: The dependency may look like inheritance but not necessarily. For example: Monad implements both “Applicative” and “Chain” specs (in addition to others).

Fantasy-Land Spec compliant Libraries

There are several libraries that implement FL spec. For example: monet.js, barely-functional, folktalejs, ramda-fantasy (based on Ramda), immutable-ext (based on ImmutableJS), Fluture and more.

What Libraries Should I Use?

Libraries like lodash-fp, ramdajs, only enable you to start writing in FP style. But they don’t provide functions to use key mathematical concepts like Monads, Functors, Foldables to actually solve real-world problems.

So, in addition to them you’ll have to use one of the libraries that follow fantasy-land spec. Some such libraries are: monet.js, barely-functional, folktalejs, ramda-fantasy (based on Ramda), immutable-ext (based on ImmutableJS), Fluture and more.

Note: I’m using ramdajs and ramda-fantasy

OK, now that we know the basics, Let’s see some practical examples and learn various FP features and techniques through those examples.

Example 1 — Dealing With Null Checks

Topics covered: Functors, Monads, Maybe Monad, Currying.

Use-case: We want to show different index webpage depending on the user’s “primary” language (inside user’s prefs, see below). And we need to write getUrlForUser that returns appropriate URL from the list of URLs(indexURLs) for the user’s (joeUser) primary language(“spanish”).

The problem is: the primary language could be null. The user itself could be null (not logged in). The primary language might not be available in our list of indexURLs. So we’ll have to take care of lots of “nulls” or “undefined”.

Solution (Imperative Vs FP):

PS: Don’t worry if the FP version looks hard to understand, I’ll cover them step-by-step later in this post.

OK, Let’s first understand several FP concepts and techniques used in this solution.

Functors

Any class(or construction function) or a datatype that stores a value and implements “map” method is called a “Functor”.

For example: An Array is a “Functor”. Because an Array can store values and has “map” method that allows us to map a function to the values it’s storing.

const add1 = (a) => a+1;
let myArray = new Array(1, 2, 3, 4); //store values
myArray.map(add1) // -> [2,3,4,5] //applies functions

Let’s write our own Functor “MyFunctor”. It’s simply a JS class (constructor function) that stores some value and implements a “map” method. This “map” method applies the function to the stored value and then creates a new Myfunctor from the result and returns that new MyFunctor.

PS: Functors also need to implement other specs (see Fantasyland specs) in addition to “map” but I’m not going to cover them here.

Monads

Monads are also Functors, i.e. they have “map” method but implements more methods than just “map”. If you look at the spec dependency graph again, you’ll see that also need to implement various other features in different specs like: “Apply” (ap method), “Applicative” (ap and of method), and “Chain” (chain method).

Simplified Explanation: In JS, Monads are classes or constructor functions that store some data and implements “map”, “ap”, “of” and “chain” methods that do something with the stored data as per spec.

Below is a sample implementation so you get an idea of the internals of the Monad.

A sample implementation of a Monad

Now, the generic Monads are not typically used but more specific and more useful Monads like “Maybe Monad” or “Either Monad” are often used in FP programming. So, let’s take a look at “Maybe Monad”.

“Maybe” Monad

A “Maybe” Monad is a class that implements Monad spec. But the special thing about Monad is that it takes care of “null” or “undefined” values.

Specifically, if the data stored is a null or undefined, then it’s “map” function doesn’t run the given function at all and there by avoiding any null or undefined issues. It is used in situations where we are dealing with Null values.

Below code shows ramda-fantasy’s implementation of Maybe Monad. It creates an instance of one of the two different sub-classes, Just or Nothing, depending on the value (i.e. useful value V/s null/undefined respectively).
While both Just and Nothing has similar methods (map, orElse etc), Just’s actually does something but Nothing’s doesn’t do anything.
Give special attention to “map” and “orElse” methods below
Snippets from ramda-fantasy’s Maybe implementation

Let’s see how to use Maybe monad to deal with “null” checks.

Follow these steps:

  1. If there any object that might be null or have null properties, create a Monad object out of it.
  2. Use some libraries like ramdajs, that are “Maybe-aware” to access value from w/in the Monad and work on it.
  3. Provide a default value if the actual value happens to be null (i.e handle Null errors upfront).

Currying — (Helps Dealing With Global Data And Multi-Param Functions)

Topics covered: Pure functions and Composition

If we want to chain a series of functions together like: func1.func2.func3 or (func1(func2(func3())), all these functions can only receive just one input parameter each. For example, if func2 takes two parameters func2(param1, param2), then we can’t chain it!

But the practically speaking, many functions take multiple parameters. So how to use them in composition? Solution: “Currying”.

Currying converts a function that takes multiple parameter into a function that takes a single parameter at a time. It wont run the function until all parameters are passed.

In addition, Currying can also be used in situations when we are accessing global values. i.e. make it “pure”.

Let’s look at our solution again:

Example 2— Handling Error Throwing Functions And Exiting Immediately After An Error

Topics Covered: “Either Monad”

Maybe Monad is great if we have “default” values to replace Null errors. But what about functions that actually need to throw errors? And how to know which function threw the error when we chain multiple error-throwing functions (i.e. we want fast-failure)?

For example: If we have func1.func2.func3… and if func2 threw an error, we should skip func3 and other future functions and properly show error from func2 so we can handle it.

Either Monad

Either Monads are great for dealing with multiple functions when they all can potentially throw error and want to quit immediately after an error so that we can pin-point where the error occurred.

Use case: For example in the below imperative snippet, we are calculating “tax” and “discount” for items and ultimately displaying showTotalPrice.

Note that the “tax” function will throw error if the price is non-numeric. Similarly, “discount” function will throw error if price is non-numeric and it will also throw error if the item’s price is less than 10.

So showTotalPrice has multiple error checks.
Imperative example that can be improved by using Either Monad

Let’s see how showTotalPrice can be improved by using Either Monad and rewrite everything in FP style.

Either Monad provides two constructors: “Either.Left” and “Either.Right”. Think of them as subclasses of Either. Both “Left” and “Right” are Monads! The idea is to store errors/exceptions in Left and useful values in Right.

i.e. create an instance of Either.Left or Either.Right depending on the value. Once we do that we can run map, chain and so on on those values to compose them.

While both Left and Right provide “map”, “chain” and so on, Left constructor doesn’t do anything as it stored Errors. Where as the Right constructor implements all the functions as it contains actual result.

OK, Let’s see how to change our imperative example to FP

Step 1: Wrap return values with Left and Right

Note: “Wrap” means create an instance of some Class. These functions internally call “new” so we don’t have to.

Step 2: Wrap the initial value in Right because it’s a valid value and so we can compose it.

const getItemPrice = (item) => Right(item.price);

Step 3: Create two functions, one to handle eventual error and another to handle result. And warp them in Either.either (this is from ramda-fantasy.js api).

Either.either takes 3 params. success handler, an error handler and an "Either" Monad. Either is curried. So we can just pass the handlers for now and pass the Either (3rd param) later.
Once Either.either receives all 3 params, it passes the 3rd param "Either" to the success handler or error handler depending of if the Either is "Right" or "Left" respectively.
const displayTotal = (total) => { console.log(‘Total Price: ‘ + total) };
const logError = (error) => { console.log(‘Error: ‘ + error.message); };
const eitherLogOrShow = Either.either(logError, displayTotal);

Step 4: Use “chain” method to compose multiple error throwing functions. Pass their result to Either.either (eitherLogOrShow) which will take care of passing the result to success handler or failure handler.

const showTotalPrice = (item) => eitherLogOrShow(getItemPrice(item).chain(apply25PercDisc).chain(addCaliTax));

Putting it all together:

Thank you for reading! If you liked the post please 💚 and share it on Twitter!🙏🏼

LATEST: Functional Programming In JS — With Practical Examples (Part 2)

My Other Posts

Functional Programming

  1. JavaScript Is Turing Complete — Explained
  2. Functional Programming In JS — With Practical Examples (Part 1)
  3. Functional Programming In JS — With Practical Examples (Part 2)

ES6

  1. 5 JavaScript “Bad” Parts That Are Fixed In ES6
  2. Is “Class” In ES6 The New “Bad” Part?

WebPack

  1. Webpack — The Confusing Parts
  2. Webpack & Hot Module Replacement [HMR] (under-the-hood)
  3. Webpack’s HMR And React-Hot-Loader — The Missing Manual

Draft.js

  1. Why Draft.js And Why You Should Contribute
  2. How Draft.js Represents Rich Text Data

React And Redux :

  1. Step by Step Guide To Building React Redux Apps
  2. A Guide For Building A React Redux CRUD App (3-page app)
  3. Using Middlewares In React Redux Apps
  4. Adding A Robust Form Validation To React Redux Apps
  5. Securing React Redux Apps With JWT Tokens
  6. Handling Transactional Emails In React Redux Apps
  7. The Anatomy Of A React Redux App

Salesforce

  1. Developing React Redux Apps In Salesforce’s Visualforce