Skip to content

Instantly share code, notes, and snippets.

@welteki
Last active January 29, 2020 00:15
Show Gist options
  • Save welteki/79177e5950daf0f2574e2f861b5f4c8b to your computer and use it in GitHub Desktop.
Save welteki/79177e5950daf0f2574e2f861b5f4c8b to your computer and use it in GitHub Desktop.
Monet.js Free monad DSL and interpreter example
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('--------------------------------');
@welteki
Copy link
Author

welteki commented Jan 29, 2020

Key value store DSL and interpreter example

This is a Javascript implementation of the KVS example linked in the monet.js docs. It is a rewrite of the KVS example in the fantasy-frees repository.

Run this example on Repl.it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment