Last active
January 13, 2016 00:09
-
-
Save nbenns/452fbb43dfa336d77ec6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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