// Implementing Array Applicative
Array.prototype.ap = function ( ...args )
{
const loop = ( acc , [ x , ...xs ] ) =>
x === undefined
? [ this [ 0 ] ( ...acc ) ]
: x.chain ( a =>
loop ( acc.concat ( [ a ] ) , xs ) )
return loop ( [] , args )
}
// Implementing Array Monad
Array.prototype.chain = function chain (f)
{
return this.reduce ( ( acc , x ) =>
acc.concat ( f (x) ), [] )
}
// Utilizing the implemented functions
const combinations = ( ...xxs ) =>
[ ( ...xs ) => xs ] .ap ( ...xxs )
console.log ( combinations ( array1 , array2 , array3 ) )
// [ [ 'a1', 'a2', 'a3' ],
// [ 'a1', 'a2', 'b3' ],
// [ 'a1', 'a2', 'c3' ],
// [ 'a1', 'b2', 'a3' ],
// [ 'a1', 'b2', 'b3' ],
// [ 'a1', 'b2', 'c3' ],
// [ 'b1', 'a2', 'a3' ],
// [ 'b1', 'a2', 'b3' ],
// [ 'b1', 'a2', 'c3' ],
// [ 'b1', 'b2', 'a3' ],
// [ 'b1', 'b2', 'b3' ],
// [ 'b1', 'b2', 'c3' ],
// [ 'c1', 'a2', 'a3' ],
// [ 'c1', 'a2', 'b3' ],
// [ 'c1', 'a2', 'c3' ],
// [ 'c1', 'b2', 'a3' ],
// [ 'c1', 'b2', 'b3' ],
// [ 'c1', 'b2', 'c3' ],
// [ 'd1', 'a2', 'a3' ],
// [ 'd1', 'a2', 'b3' ],
// [ 'd1', 'a2', 'c3' ],
// [ 'd1', 'b2', 'a3' ],
// [ 'd1', 'b2', 'b3' ],
// [ 'd1', 'b2', 'c3' ] ]