Skip to content

Instantly share code, notes, and snippets.

@nbenns
Last active January 13, 2016 00:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nbenns/452fbb43dfa336d77ec6 to your computer and use it in GitHub Desktop.
Save nbenns/452fbb43dfa336d77ec6 to your computer and use it in GitHub Desktop.
'use strict';
const R = require('ramda');
/*
* Mathematically, Monoids are a SemiGroup with an identity element.
*
* Monoids are defined under a certain operation, they require 3 things:
* the operation must be associative, so op(op(A,B),C) == op(A,op(B,C))
* an identity (sometimes called the Zero) such that type op(A, I) = A and op(I, A) = A,
* and it must return the same type, so C = op(A,B) where A, B, and C are all type T
* in otherwords the set must be closed under this operation.
*
* I don't prove the facts here, but use the fact that Integers are closed under addition
* and have an identity of 0 (3 + 0 = 0, 0 + 3 = 0).
*
* The reason to use a Monoid is to be able to pause the operation and pick it up later when
* more data is received.
*/
// An array of Basket line items
const basket = [[2, 'blah', 9.95, 19.9], [1, 'meow', 2.00, 2.00], [1, 'haha', 9.99, 9.99]];
// A Monoid Zero for conversion of basket items and reduction
const offerMZero = {
products: {
meow: 0,
blah: 0
}
}
// Convert a basket item to a Monoid for the offer
const basket2OfferM = R.curry((Zero, b) => {
let tmp = R.clone(Zero);
if (tmp.products[b[1]] !== undefined) tmp.products[b[1]] = b[0];
return tmp;
})
// Reduces a list of Monoids to a single one
const offerMSum = (o1, o2) => {
let tmp = R.clone(o1);
Object.keys(tmp.products).forEach(k => {
tmp.products[k] = tmp.products[k] + o2.products[k];
})
return tmp;
}
// Map all basket items to Monoids
const offerMs = basket.map(basket2OfferM(offerMZero));
console.log(offerMs);
/*
* [ { products: { meow: 0, blah: 2 } },
* { products: { meow: 1, blah: 0 } },
* { products: { meow: 0, blah: 0 } } ]
*/
// Reduce to a Monoid under an Sum operation
const output = offerMs.reduce(offerMSum, offerMZero)
console.log(output);
// { products: { meow: 1, blah: 2 } }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment