Last active
January 20, 2017 06:48
-
-
Save evilsoft/3b567f099ede038991426d2775cb1412 to your computer and use it in GitHub Desktop.
Concat to compose a Star...
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 isFunction = require('../predicates/isFunction') | |
const isType = require('../internal/isType') | |
const _inspect = require('../internal/inspect') | |
const compose = require('../helpers/compose') | |
const identity = require('../combinators/identity') | |
const constant = require('../combinators/constant') | |
const Pair = require('./Pair') | |
const _type = | |
constant('Arrow') | |
const _empty = | |
() => Arrow(identity) | |
function Arrow(runWith) { | |
if(!isFunction(runWith)) { | |
throw new TypeError('Arrow: Function required') | |
} | |
const type = | |
_type | |
const empty = | |
_empty | |
const value = | |
constant(runWith) | |
const inspect = | |
constant(`Arrow${_inspect(value())}`) | |
function concat(m) { | |
if(!(m && isType(type(), m))) { | |
throw new TypeError('Arrow.concat: Arrow required') | |
} | |
return map(m.runWith) | |
} | |
function map(fn) { | |
if(!isFunction(fn)) { | |
throw new TypeError('Arrow.map: Function required') | |
} | |
return Arrow(compose(fn, runWith)) | |
} | |
function contramap(fn) { | |
if(!isFunction(fn)) { | |
throw new TypeError('Arrow.contramap: Function required') | |
} | |
return Arrow(compose(runWith, fn)) | |
} | |
function promap(l, r) { | |
if(!isFunction(l) || !isFunction(r)) { | |
throw new TypeError('Arrow.promap: Functions required for both arguments') | |
} | |
return Arrow(compose(r, runWith, l)) | |
} | |
function first() { | |
return Arrow(function(x) { | |
if(!(x && x.type && x.type() === Pair.type())) { | |
throw TypeError('Arrow.first: Pair required for inner argument') | |
} | |
return x.bimap(runWith, identity) | |
}) | |
} | |
function second() { | |
return Arrow(function(x) { | |
if(!(x && x.type && x.type() === Pair.type())) { | |
throw TypeError('Arrow.second: Pair required for inner argument') | |
} | |
return x.bimap(identity, runWith) | |
}) | |
} | |
return { | |
inspect, type, value, runWith, | |
concat, empty, map, contramap, | |
promap, first, second | |
} | |
} | |
Arrow.empty = _empty | |
Arrow.type = _type | |
module.exports = Arrow |
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 { Star, safe, not, isNil } = crocks | |
const lift = | |
safe(not(isNil)) | |
const f = | |
Star(lift) | |
const g = | |
Star(x => lift(x).map(val => val * 10)) | |
log(f.concat(g).runWith(23)) |
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 isFunction = require('../predicates/isFunction') | |
const isFunctor = require('../predicates/isFunctor') | |
const isMonad = require('../predicates/isMonad') | |
const isType = require('../internal/isType') | |
const _inspect = require('../internal/inspect') | |
const identity = require('../combinators/identity') | |
const compose = require('../helpers/compose') | |
const constant = require('../combinators/constant') | |
const Pair = require('./Pair') | |
const _type = | |
constant('Star') | |
function Star(runWith) { | |
if(!isFunction(runWith)) { | |
throw new TypeError('Star: Function in the form (a -> f b) required') | |
} | |
const type = | |
_type | |
const inspect = | |
constant(`Star${_inspect(runWith)}`) | |
function concat(s) { | |
if(!(s && isType(type(), s))) { | |
throw new TypeError('Star.concat: Star required') | |
} | |
return Star(function(x) { | |
const m = runWith(x) | |
if(!isMonad(m)) { | |
throw new TypeError('Star.concat: Internal function must return a Monad') | |
} | |
return m.chain(function(val) { | |
const inner = s.runWith(val) | |
if(!(inner && isType(m.type(), inner))) { | |
throw new TypeError('Star.concat: Internal functions must return same the type') | |
} | |
return inner | |
}) | |
}) | |
} | |
function map(fn) { | |
if(!isFunction(fn)) { | |
throw new TypeError('Star.map: Function required') | |
} | |
return Star(function(x) { | |
const m = runWith(x) | |
if(!isFunctor(m)) { | |
throw new TypeError('Star.map: Internal function must return a Functor') | |
} | |
return m.map(fn) | |
}) | |
} | |
function contramap(fn) { | |
if(!isFunction(fn)) { | |
throw new TypeError('Star.contramap: Function required') | |
} | |
return Star(compose(runWith, fn)) | |
} | |
function promap(l, r) { | |
if(!isFunction(l) || !isFunction(r)) { | |
throw new TypeError('Star.promap: Functions required for both arguments') | |
} | |
return Star(function(x) { | |
const m = runWith(l(x)) | |
if(!isFunctor(m)) { | |
throw new TypeError('Star.promap: Internal function must return a Functor') | |
} | |
return m.map(r) | |
}) | |
} | |
function first() { | |
return Star(function(x) { | |
if(!isType(Pair.type(), x)) { | |
throw TypeError('Star.first: Pair required for inner argument') | |
} | |
const m = runWith(x.fst()) | |
if(!isFunctor(m)) { | |
throw new TypeError('Star.first: Internal function must return a Functor') | |
} | |
return m.map(l => Pair(l, x.snd())) | |
}) | |
} | |
function second() { | |
return Star(function(x) { | |
if(!isType(Pair.type(), x)) { | |
throw TypeError('Star.second: Pair required for inner argument') | |
} | |
const m = runWith(x.snd()) | |
if(!isFunctor(m)) { | |
throw new TypeError('Star.second: Internal function must return a Functor') | |
} | |
return m.map(r => Pair(x.fst(), r)) | |
}) | |
} | |
return { | |
inspect, type, runWith, concat, map, | |
contramap, promap, first, second | |
} | |
} | |
Star.type = _type | |
module.exports = Star |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment