Last active
January 29, 2020 00:15
-
-
Save welteki/79177e5950daf0f2574e2f861b5f4c8b to your computer and use it in GitHub Desktop.
Monet.js Free monad DSL and interpreter example
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
const { compose, identity, add, always, dissoc, assoc } = require('ramda') | |
const { taggedSum, tagged } = require('daggy'); | |
const { Free } = require('monet'); | |
const KVS = taggedSum('KVS', { | |
Put: ['key', 'val', 'next'], | |
Del: ['key', 'next'], | |
Get: ['key', 'val'] | |
}); | |
KVS.prototype.map = function(f) { | |
return this.cata({ | |
Put: (k, v, n) => KVS.Put(k, v, f(n)), | |
Del: (k, n) => KVS.Del(k, f(n)), | |
Get: (k, v) => KVS.Get(k, compose(f, v)) | |
}) | |
} | |
const unit = tagged('unit', ['x']) | |
const Unit = () => unit('') | |
const put = (key, val) => Free.liftF(KVS.Put(key, val, Unit())) | |
const del = key => Free.liftF(KVS.Del(key, Unit())) | |
const get = key => Free.liftF(KVS.Get(key, identity)) | |
const modify = (key, f) => | |
get(key).chain(v => put(key, f(v))) | |
const interpreters = { | |
string: (free, store) => { | |
function go(store, free, strs) { | |
return free.resume().fold( | |
x => x.cata({ | |
Put: (k, v, n) => go(assoc(k, v, store), n, strs.concat(`Putting ${k} with ${v}`)), | |
Del: (k, n) => go(dissoc(k, store), n, strs.concat(`Deleting ${k}`)), | |
Get: (k, f) => go(store, f(store[k]), strs.concat(`Getting ${k}`)) | |
}), | |
always(strs.join('\n')) | |
) | |
} | |
return go(store, free, []) | |
}, | |
pure: (free, store) => | |
free.resume().fold( | |
x => x.cata({ | |
Put: (k, v, n) => interpreters.pure(n, assoc(k, v, store)), | |
Del: (k, n) => interpreters.pure(n, dissoc(k, store)), | |
Get: (k, f) => interpreters.pure(f(store[k]), store) | |
}), | |
always(store) | |
) | |
} | |
const script = get('swiss bank account id').chain(id => { | |
return modify(id, add(1000)) | |
.chain(() => put('bermuda airport', 'getaway car')) | |
.chain(() => del('tax records')) | |
}) | |
const store = { | |
'swiss bank account id': 'xxxx1', | |
'xxxx1': 5032.12, | |
'tax records': [ | |
{'date': '2/20/15', 'subject': 'aaaaa', 'amount': 2322.90 }, | |
{'date': '2/20/15', 'subject': 'bbbbb', 'amount': 3412.90 }, | |
{'date': '2/20/15', 'subject': 'ccccc', 'amount': 4502.90 }, | |
{'date': '2/20/15', 'subject': 'ddddd', 'amount': 5692.90 } | |
] | |
} | |
console.log('--------------------------------'); | |
console.log(interpreters.string(script, store)); | |
console.log('--------------------------------'); | |
console.log(interpreters.pure(script, store)); | |
console.log('--------------------------------'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Key value store DSL and interpreter example
Run this example on Repl.it