In software circles, a design pattern is a methodology and documented approach to a problem and its solution which is bound to be found repeatedly in several projects as a tumbling block. Software engineers customize these patterns according to their problem and form a solution for their respective applications. Patterns follow a formal structure to explain a problem and then go over a proposed answer as well as key points which are related to either the problem or the solution. A good pattern is one which is well known in the industry and used by the IT masses. For functional programming, there are several popular design patterns. Let’s go over some of these.
Monad
Monad is a design pattern which takes several functions and integrates them as a single function. It can be seen as a type of combinatory and is a core component of functional programming. In monad, a value is wrapped in a box which is then unwrapped and a function is passed to use the wrapped value.
To go into more technicalities, a monad can be classified into running on three basic principles.
· A parameterized type M<T>
According to this rule, T can possess any type like String, Integer, hence it is optional.
· A unit function T -> M<T>
According to this rule, there can be a function taking a type and its processing may return “Optional”. For instance, Optional.of(String) returns Optional<String>.
· A bind operation: M<T> bind T -> M <U> = M<U>
According to this rule which is also known as showed operator due to the symbol >>==. For the monad, the bind operator is called. For instance, Optional<Integer>. Now this takes a lambda or function as an argument for instance like (Integer -> Optional<String> and returns and processes a Monad which has a different type.
Persistent Data Structures
In computer science, there is a concept known as a persistent data structure. Persistent data structure at their essence work like normal data structure but they preserve their older versions after modification. This means that these data structures are inherently immutable because apparently, the operations performed in such structures do not modify the structure in place. Persistent data structures are divided into three types:
- When all the versions of a data structure can be accessed and only the latest version can be changed, then it is a partially persistent data structure.
- When all the versions of a data structure can be accessed as well as changed, then it is a fully persistent data structure.
- Sometimes due to a merge operation, a new version can be generated from two prior versions; such type of data structure is known as confluently persistent.
For data structure which does not show any persistence, the term “ephemeral” is used.
As you may have figured out by now, since persistent data structures enforce immutability, they are used heavily in functional programming. You can find persistent data structure implementations in all major functional programming language. For instance, in JavaScript Immutable.js is a library which is used for implementing persistent data structures. For example,
import { MapD } from ‘immutable’;
let employee = Map({
employeeName: ‘Brad’,
age: 27
});
employee.employeeName; // -> undefined
employee.get(’employeeName’); // -> ‘Brad’
Functors
In programming, containers are used to store data without assigning any method or properties to them. We just put a value inside a container which is then passed with the help of functional programming. A container only has to safely store the value and provide it to the developer in need. However, the values inside them cannot be modified. In functional programming, these containers provide a good advantage because they help with forming the foundation of functional construct and assist with asynchronous actions and pure functional error handling.
So why are we talking about containers? Because functors are a unique type of container. Functors are those containers which are coded with “map” function.
Among the simplest type of containers, we have arrays. Let’s see the following line in JavaScript.
const a1 = [10, 20,30, 40, 50];
Now to see a value of it, we can write.
Const x=y[1];
In functional, the array cannot be changed like.
a1.push(90)
However, new arrays can be created from an existing array. An array is theoretically a function. Technically, whenever a unary function is mapped with a container, then it is a functor. Here ‘mapped’ means that the container is used with a special function which is then applied to a unary function. For arrays, the map function is the special function. A map function processes the contents of an array and performs a special function for all the elements of the element step-by-step after which it responds with another array.
Zipper
A zipper is a design pattern which is used for the representation of an aggregate data structure. Such a pattern is good for codes where arbitrarily traversal is common and the contents can be modified, therefore it is usually used in purely functional programming environments. The concept of Zipper dates back to 1997 where Gérard Huet introduced a “gap buffer” strategy.
Zipper is a general concept and can be customized according to data structures like trees and lists. It is especially convenient for data structures which used recursion. When used with zipper, these data structure are known as “a list with zipper” or “a tree with zipper” for making it apparent that their implementation makes use of zipper pattern.
In simple terms, zipper with data structure has a hole. They are used for the manipulation and traversal in data structures where the hole indicates the present focus for the traversal. Zipper facilitates developers to easily move within the data structure.