Skip to content

Instantly share code, notes, and snippets.

@evilsoft
Last active January 20, 2017 06:48
Show Gist options
  • Save evilsoft/3b567f099ede038991426d2775cb1412 to your computer and use it in GitHub Desktop.
Save evilsoft/3b567f099ede038991426d2775cb1412 to your computer and use it in GitHub Desktop.
Concat to compose a Star...
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
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))
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