Created
February 27, 2016 16:38
-
-
Save DrBoolean/3f5ac08a5bf1c4673757 to your computer and use it in GitHub Desktop.
Free(er) Monads Pt2
This file contains hidden or 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 daggy = require('daggy') | |
const Task = require('data.task') | |
const _ = require('lodash') | |
const kleisli_comp = (f, g) => x => f(x).chain(g) | |
const compose = (f, g) => x => f(g(x)) | |
const id = x => x | |
//=============FREE============= | |
const Free = daggy.taggedSum({Impure: ['x', 'f'], Pure: ['x']}) | |
const {Impure, Pure} = Free | |
Free.of = Pure | |
Free.prototype.map = function(f) { | |
return this.chain(a => Free.of(f(a))) | |
} | |
Free.prototype.chain = function(f) { | |
return this.cata({ | |
Impure: (x, g) => Impure(x, kleisli_comp(g, f)), | |
Pure: x => f(x) | |
}) | |
} | |
Free.prototype.foldMap = function(interpreter, of) { | |
return this.cata({ | |
Pure: a => of(a), | |
Impure: (intruction_of_arg, next) => | |
interpreter(intruction_of_arg).chain(result => | |
next(result).foldMap(interpreter, of)) | |
}) | |
} | |
const liftF = command => Impure(command, Pure) | |
//=============IO via FREE============= | |
const IO = daggy.taggedSum({IO: ['f']}) | |
const io = compose(liftF, IO.IO) | |
//=============Maybe via FREE============= | |
const Maybe = daggy.taggedSum({ Just: ['x'], Nothing: [] }) | |
const {Just, Nothing} = Maybe | |
const just = compose(liftF, Just) | |
const nothing = liftF(Nothing) | |
//=============Examples============= | |
const data = {user: {name: 'jerry'}} | |
const safeProp = (k, o) => o[k] ? just(o[k]) : nothing | |
const localStorage = io(() => data) | |
const printLn = x => io(() => console.log(x)) | |
const maybeToTask = m => m.cata({Just: Task.of, Nothing: Task.rejected}) | |
const ioToTask = i => new Task((rej, res) => res(i.f())) | |
const maybe_name = safeProp('user', data) | |
.chain(u => safeProp('name', u)) | |
.map(n => n.toUpperCase()) | |
maybe_name.foldMap(maybeToTask, Task.of).fork(console.error, console.log) | |
// JERRY | |
const i = localStorage | |
.map(l => l.user) | |
.chain(printLn) | |
i.foldMap(ioToTask, Task.of).fork(console.error, id) | |
// {name: 'jerry'} | |
const dispatch = pairs => | |
instruction_of_arg => { | |
const interpreter = _.find(pairs, ([type, inter]) => | |
instruction_of_arg.constructor === type)[1] | |
return interpreter(instruction_of_arg) | |
} | |
const interpret = dispatch([[IO, ioToTask], | |
[Maybe, maybeToTask]]) | |
const printName = localStorage | |
.chain(ls => safeProp('user', ls)) | |
.chain(u => safeProp('name', u)) | |
.map(n => n.toUpperCase()) | |
.chain(printLn) | |
printName.foldMap(interpret, Task.of).fork(console.error, id) | |
// JERRY |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Code for https://www.youtube.com/watch?v=KFCEJUjsdQg