/fp

Functional Programming Practice Exercises

Primary LanguageTypeScript

Functional Programming Practice

This repository includes array, collection, object and other example manupulations using functional programming practices. Most of the excercises were mentioned here

Getting Started

To clone this repository

git clone https://github.com/ansaries/fp.git

Then run

npm install

I have used parcel for packaging and hot reload, so to run it use

parcel ./src/index.html

or just type in your console

npm start

API Index

Functions

merge_with(fn)Object

Merges Multiple Objects into one final Object with applied maping method

memoize(fn)function

Memoize a funtion based on its arguments

compose(...fns)function

Compose pipes all methods from right to left The return value of last(right) method will be injected into the arguments of next(left) method.

flow(...fns)function

Flow pipes all methods from left to right The return value of first(left) method will be injected into the arguments of next(right) method.

pushItem(...args)Array.<any>

Pushes an Item in Array and returns the Array with the new Item

concatAll()Array.<T>

Concat all arrays

concatMap(fn)Array.<T>

Concat all arrays while applying a Map function on each element of each array

flip()Array.<T>

Revese the array

flatten(initial)Array.<T>

Flattens a multi-dimensional array of any depth

insert(item, i)Array.<T>

Insert an item on a specified location and shift all of the rest to right.

reject(mapFn)

Returns items that does not full fill the filterFn

clist(...args)Array.<any>

Converts arguments to array

take(x, ar)Array.<T>

Take a slice of array starting at 0 to x from an array ar

range(N)Array.<number>

Similar to range method of Python, creates an array of number from 1 to N

frequencies()function

Takes a sequence and counts how many times the elements appear in the sequence, returns a map.

interleaveNfn(...args)Array.<any>

Iterative Implementation of Interleave Time Complexity O(n) Interleaving is transposing two dimensional array and then concating or flattening it.

interleaveFn(...args)Array.<any>

Functional Implementation of Interleave Interleaving is transposing two dimensional array and then concating or flattening it.

zip(...args)Array.<any>

Transposes multi dimensional array

transpose(...args)Array.<any>

Transpose multi dimensional array

zipWith(fn)function

Accumulating the multi dimensional array using a accumulator method

zipMapWith(fn, initialValue)*

Takes a map function to apply on the array taken by composed function.

zipDic(left, right)Object

Creates an object from two arrays

zipMap(left, right, mapFn)Array.<(Object|any)>

Zips two arrays and maps out the output using the mapFn

update(obj, prop, mapFn, val)T

Updates a particular propery of an object using the mapFn function

update_in(obj, propMap, mapFn, val)T

Updates a particular property in a deep object tree using a map of keys and a map function.

API Description

merge_with(fn) ⇒ Object

Merges Multiple Objects into one final Object with applied maping method

Kind: global function

Param Type
fn function

Example

merge_with(add, {"a": 1, "b": 2}, {"b": 2}) => {"a": 1, "b": 4}

Example

merge_with(sub, {"a": 1, "b": 2}, {"b": 2}) => {"a": 1, "b": 0}
// Similar to zipWith() for arrays

memoize(fn) ⇒ function

Memoize a funtion based on its arguments

Kind: global function
Summary:

Memoization requires that the passed function should be a pure-function


Returns: function -

return a reusable function

Param Type Description
fn function

Pure Function

Example

const summemo = memoize(add);
const submemo = memoize(sub);
summemo(4, 6); // Computes 4 + 6 => 10
submemo(4, 6); // Computes 4 - 6 => -2
summemo(4, 6); // Does not compute, rather return from cash => 10
submemo(4, 6); // Does not compute, rather return from cash => -2

compose(...fns) ⇒ function

Compose pipes all methods from right to left The return value of last(right) method will be injected into the arguments of next(left) method.

Kind: global function
Returns: function -

Returns a function which takes any argument

Param Type Description
...fns Array.<function()>

one or more functions as arguments to apply composedly

Example

// Suppose you want to get Grand Total of a cart after Tax and Discount.
var getGrandTotal = compose(Math.round, add);
// grandTotal = subTotalCart + Vat + Gst - Discount
var grandTotal = getGrandTotal(
  subTotalCart,
  VAT(subTotalCart),
  GST(subTotalCart),
  negative(Discount(subTotalCart))
);
// Suppose for no EU customer the Vat does not apply
var nonUsGrandTotal = getGrandTotal(
  subTotalCart,
  GST(subTotalCart),
  negative(Discount(subTotalCart))
);

flow(...fns) ⇒ function

Flow pipes all methods from left to right The return value of first(left) method will be injected into the arguments of next(right) method.

Kind: global function
Returns: function -

Returns a function which takes any argument

Param Type Description
...fns Array.<function()>

one or more functions as arguments to apply composedly

Example

// Suppose you want to get Grand Total of a cart after Tax and Discount.
var getGrandTotal = flow(add, Math.round);
// grandTotal = subTotalCart + Vat + Gst - Discount
var grandTotal = getGrandTotal(
  subTotalCart,
  VAT(subTotalCart),
  GST(subTotalCart),
  negative(Discount(subTotalCart))
);
// Suppose for no EU customer the Vat does not apply
var nonUsGrandTotal = getGrandTotal(
  subTotalCart,
  GST(subTotalCart),
  negative(Discount(subTotalCart))
);

pushItem(...args) ⇒ Array.<any>

Pushes an Item in Array and returns the Array with the new Item

Kind: global function

Param Type
...args *

concatAll() ⇒ Array.<T>

Concat all arrays

Kind: global function

concatMap(fn) ⇒ Array.<T>

Concat all arrays while applying a Map function on each element of each array

Kind: global function

Param Type
fn function

Example

[[1, 2, 3], [4, 5], [6]].concatMap(add); // => [1,3,5,7,9,11]

flip() ⇒ Array.<T>

Revese the array

Kind: global function

flatten(initial) ⇒ Array.<T>

Flattens a multi-dimensional array of any depth

Kind: global function

Param Type
initial *

Example

[[1],[[[2]],[[[[[3]]]]]].flatten(); // => [1,2,3,4]

insert(item, i) ⇒ Array.<T>

Insert an item on a specified location and shift all of the rest to right.

Kind: global function

Param Type Default
item T
i number 0

Example

[1,3,4,5,6].insert(2,1) => [1,2,3,4,5,6]

reject(mapFn)

Returns items that does not full fill the filterFn

Kind: global function

Param Type Description
mapFn function

(x: any, i: number) => Array

clist(...args) ⇒ Array.<any>

Converts arguments to array

Kind: global function
Returns: Array.<any> -

Return an Array of type any

Param Type Description
...args any

Arguments of type any

Example

clist(1,2,3,4,5); => [1,2,3,4,5]

take(x, ar) ⇒ Array.<T>

Take a slice of array starting at 0 to x from an array ar

Kind: global function

Param Type
x number
ar Array.<any>

range(N) ⇒ Array.<number>

Similar to range method of Python, creates an array of number from 1 to N

Kind: global function

Param Type
N number

Example

range(10) => [1,2,3,4,5,6,7,8,9,10]

frequencies() ⇒ function

Takes a sequence and counts how many times the elements appear in the sequence, returns a map.

Kind: global function
Example

frequencies()("aabcbcac"); => {'a': 3, 'c': 3, 'b': 2}
frequencies()([1, 2, 2, 2]); => {1: 1, 2: 3}

interleaveNfn(...args) ⇒ Array.<any>

Iterative Implementation of Interleave Time Complexity O(n) Interleaving is transposing two dimensional array and then concating or flattening it.

Kind: global function

Param Type
...args *

Example

interleaveNfn([1, 2, 3], [4, 5, 6], [7, 8, 9]); //=> [1,4,7,2,5,8,3,6,9]
// Implementation is as follows:
function interleaveNfn(...args) {
  const arr = [];
  const length = args.length;
  const inerLength = args[0].length;
  for (let i = 0; i < length; i++)
    for (let j = 0; j < inerLength; j++) {
      arr.push(args[j][i]);
    }
  return arr;
}

interleaveFn(...args) ⇒ Array.<any>

Functional Implementation of Interleave Interleaving is transposing two dimensional array and then concating or flattening it.

Kind: global function

Param Type
...args *

Example

interleaveFn([1, 2, 3], [4, 5, 6], [7, 8, 9]); //=> [1,4,7,2,5,8,3,6,9]
// Implementation is as follows:
export function interleaveFn(...args) {
  // Simple Declarative way
  // transpose([1,2,3],[4,5,6],[7,8,9]) => [[1,4,7],[2,5,8],[3,6,9]]
  // [[1,4,7],[2,5,8],[3,6,9]].concatAll() => [1,4,7,2,5,8,3,6,9]
  return transpose(...args).concatAll();
}

zip(...args) ⇒ Array.<any>

Transposes multi dimensional array

Kind: global function

Param Type
...args *

Example

[[1,2,3], [4,5,6], [7,8,9]] => [[1,4,7],[2,5,8],[3,6,9]]

Example

[[1, 2, 3], [4, 5, 6]].zip() => [[1, 4], [2, 5], [3, 6]]
// Implementation is as follows:
function zip(...args) {
   return args.reduce((p, c, i) => {
     if (p.length <= 0)
         // [1,2,3] => [[1],[2],[3]]
         return c.reduce((cp, cc) => cp.pushItem([cc]), []);

     else
         // [[1],[2],[3]] => [[1,4,...], [2,5,...],[3,6,...]]
         return p.map((x, i) => x.pushItem(c[i]));
    }, []);
}

transpose(...args) ⇒ Array.<any>

Transpose multi dimensional array

Kind: global function

Param Type Description
...args Array.<any>

multiple array arguments

Example

transpose([1,2,3], [4,5,6], [7,8,9]) => [[1,4,7],[2,5,8],[3,6,9]]
// Similar to
[[1, 2, 3], [4, 5, 6]].zip() => [[1, 4], [2, 5], [3, 6]]

zipWith(fn) ⇒ function

Accumulating the multi dimensional array using a accumulator method

Kind: global function
Summary:

Usefull in creating Totals for Tables, or applying discounts on each or any column etc.


Returns: function -

Returns a method which accumulates its arguments

Param Type Description
fn function

Accumulator function (x: any,y: any) => any Takes two argument x: elem of previous array y: elem of next array

Example

var getTotals = zipWith(add);
var subTotal = getTotals([1, 2, 3], [4, 5, 6], [7, 8, 9]);
// [[1,2,3], [4,5,6], [7,8,9]] => [12,15,18]

zipMapWith(fn, initialValue) ⇒ *

Takes a map function to apply on the array taken by composed function.

Kind: global function
Summary:

Uses Partial Application to first create a mapper function and then calls a reusable apply function on an array.

Param Type Description
fn function

(x:any,y:any) => any

initialValue *

Example

// Take an example of a cart like below:
const cart=[
  {"name":"Biscuits", "type":"regular", "category":"food", "price": 2.0},
 {"name":"Monitor", "type":"prime", "category":"tech", "price": 119.99},
  {"name":"Mouse", "type":"prime", "category":"tech", "price": 25.50},
  {"name":"dress", "type":"regular", "category":"clothes", "price": 49.90},
]
const subTotal = zipMapWith(sumOfPrice,0);
// where sumOfPrice works as a reducer function and then use subTotal as
const subTotalCart = subTotal(cart); =>  197
// The sumOfPrice will reduce the prices of all items of cart array.

// Lets say we have another partial application for applyDiscount then:
// Apply Discount of 10% on clothing catagory
const discountedCart = applyDiscount(10, mul)("category","clothes");
// Now reuse the subTotal method to calculate the discounted cart.
const subTotalDiscounted = subTotal(discountedCart); => 192
/////////////////////////////////////////////////////////////////////////////

zipDic(left, right) ⇒ Object

Creates an object from two arrays

Kind: global function
Summary:

Create keys from first array and values from second. First array has to be array of strings, second array could be anything. However the final object will have only as many keys as the length of left array.

Param Type
left Array.<string>
right Array.<any>

Example

// Create keys from first array and values from second.
// First array has to be array of strings
zipDic(['a','b','c'],[1,2,3]) => {a:1, b:2, c:3}

zipMap(left, right, mapFn) ⇒ Array.<(Object|any)>

Zips two arrays and maps out the output using the mapFn

Kind: global function

Param Type Description
left Array.<any>
right Array.<any>
mapFn function

(x: any, y:any) => Array

Example

// Zips two arrays to a single array.
zip([1,2,3],[4,5,6], add) => [5,7,9]

Example

// Zips two arrays to array of objects depending on map function.
zip([1,2,3],[4,5,6], (x,y,i) => ({a:x, b:y}); => [{a:1, b:4},{a:2, b:5},{a:3, b:6}]

update(obj, prop, mapFn, val) ⇒ T

Updates a particular propery of an object using the mapFn function

Kind: global function
Returns: T -

Same object with value of destination key updated using maping function.

Param Type Description
obj T

Souce Object of Type T

prop string

property name string

mapFn function

Mapping Function

val *

Assigning value

Example

// Source Object
var bob = { name: 'bob', hp: 3 };
//add 2 to to hp property of bob
// Applying mapping as addition function
// const add = (x,y) => x+y;
update(bob, 'hp', add, 2); // => {"name": "bob", "hp": 5}

update_in(obj, propMap, mapFn, val) ⇒ T

Updates a particular property in a deep object tree using a map of keys and a map function.

Kind: global function
Summary:

Use it to update a particular deeply nested field of an object. For example it can be used to apply tax on an accessory of an item in a cart.


Returns: T -

Same object with value of destination key updated using maping function.

Param Type Description
obj T

Souce Object of Type T

propMap Array.<string>

Array of strings representing the property depth

mapFn function

Mapping Function

val *

Assigning value

Example

// Source Object
var a = { a: 1, b: { c: 2, d: { e: 10 } } };
// Applying mapping as multiplication function
// const mul = (x,y) => x*y;
update_in(a, ['b', 'd', 'e'], mul, 0.9); // => {"a": 1, "b": {"c": 2, d: {e: 9}}}

Heads Up

Its personal level excercise, I tried to use vanilla to show values on Browser in a very weired manner. Just use it for inspiration, all methods and examples are not recommended for production.