Skip to content

Instantly share code, notes, and snippets.

@pfgray
Last active September 16, 2018 20:34
Show Gist options
  • Save pfgray/8707d6ae810215c83f69038d3a81c7be to your computer and use it in GitHub Desktop.
Save pfgray/8707d6ae810215c83f69038d3a81c7be to your computer and use it in GitHub Desktop.
// Do works with any Monad that implements the fantasy-land spec
// https://github.com/fantasyland/fantasy-land#monad
function Do(Type) { return (a, ...fns) => {
function doIt(as, fns) {
const [fn, ...rest] = fns;
if(rest.length === 0) {
return as['fantasy-land/chain'](a2s => {
return Type['fantasy-land/of'](fn.apply(null, a2s));
});
} else {
return as['fantasy-land/chain'](a2s => {
const aPrime = fn.apply(null, a2s);
return doIt(aPrime['fantasy-land/map']((aP) => [aP, ...a2s]), rest);
});
}
}
return doIt(a['fantasy-land/map'](a2 => [a2]), fns);
}}
/**
* Maybe from https://github.com/origamitower/folktale
*/
const Maybe = require('folktale/maybe');
const maybe =
Do(Maybe)(
Maybe.Just(5),
num => Maybe.Just(num * 2),
result => result
);
maybe // folktale:Maybe.Just({ value: 10 })
const maybe2 = Do(Maybe)(
Maybe.Just(5),
num => Maybe.Nothing(),
result => result
);
maybe2 // folktale:Maybe.Nothing({ })
/**
* Async from https://evilsoft.github.io/crocks
*/
const Async = require('crocks/Async');
const async =
Do(Async)(
Async((rej, res) => setTimeout(() => res(5), 1000)),
five => Async((rej, res) => setTimeout(() => res(2 * five), 1000)),
result => result
);
async // Async Function
async.fork(() => {}, result => {
result // 10
});
/**
* Chainable Components from https://github.com/pfgray/chainable-components
*/
const { ChainableComponent, withState } = require('chainable-components');
const React = require('react');
const composed =
Do(ChainableComponent)(
withState(3),
outer => withState(5),
(inner, outer) => ({outer, inner})
)
const element = composed.render(({outer, inner}) => (
React.createElement('div', null, `Count is: ${outer.value + inner.value}`)
))
element // is now:
// <WithState initial={3}>
// <WithState initial={5}>
// <div>Count is: 8</div>
// </WithState>
// </WithState>
/**
* The Function Monad
*/
function Func(f) {
return {
call: f,
"fantasy-land/map": g => Func(a => g(f(a))),
"fantasy-land/chain": g => {
return Func(a => {
return g(f(a)).call(a)
})
}
}
}
Func["fantasy-land/of"] = function(a) {
return Func(() => a);
}
const identity = x => x;
// do { a <- (+1); b <- (* 2); const (a + b) }
const wut =
Do(Func)(
Func(x => x + 1),
a => Func(x => x * 2),
(a, b) => Func(x => a + b),
identity
)
wut.call(14) // 43 (14+1) + (14*2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment