Skip to content

Instantly share code, notes, and snippets.

@weidagang
Forked from DrBoolean/free-er.js
Last active December 21, 2020 08:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save weidagang/bfef6aa76414213e799d345e846b0844 to your computer and use it in GitHub Desktop.
Save weidagang/bfef6aa76414213e799d345e846b0844 to your computer and use it in GitHub Desktop.
Free Monad in JavaScript
// Forked and modified from https://gist.github.com/DrBoolean/34c1d3651d1338b1b187
const daggy = require('daggy')
const compose = (f, g) => x => f(g(x))
const id = x => x
const kleisli_compose = (f, g) => x => f(x).flatMap(g)
//=============FREE=============
const Free = daggy.taggedSum({Suspend: ['x', 'f'], Pure: ['x']})
const {Suspend, Pure} = Free
Free.prototype.flatMap = function(g) {
return this.cata({
Suspend: (x, f) => Suspend(x, kleisli_compose(f, g)),
Pure: x => g(x)
})
}
Free.prototype.map = function(g) {
return this.flatMap(a => Pure(g(a)))
}
const liftF = command => Impure(command, Pure)
//=============IO via FREE=============
const IO = daggy.taggedSum({IO: ['f']})
const io = compose(liftF, IO.IO)
const unsafePerformIO = free =>
free.cata({
Pure: id,
Suspend: (m, q) =>
unsafePerformIO(q(m.f()))
})
//=============Maybe via FREE=============
const Maybe = daggy.taggedSum({ Just: ['x'], Nothing: [] })
const {Just, Nothing} = Maybe
const just = compose(liftF, Just)
const nothing = liftF(Nothing)
const runMaybe = free =>
free.cata({
Pure: x => x,
Suspend: (m, q) =>
m.cata({
Just: x => runMaybe(q(x)),
Nothing: () => Nothing
})
})
//=============Examples=============
const safeProp = (k, o) => o[k] ? just(o[k]) : nothing
const localStorage = io(() => ({preferences: 'blue'}))
const printLn = x => io(() => console.log(x))
//maybe_name :: Free (Maybe String)
const maybe_name = safeProp('user', {user: {name: 'jerry'}})
.flatMap(u => safeProp('name', u))
.map(n => n.toUpperCase())
runMaybe(maybe_name)
// JERRY
//i :: Free (IO ())
const i = localStorage
.map(l => l.preferences)
.flatMap(printLn)
unsafePerformIO(i)
// blue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment