Last active
January 1, 2018 06:21
-
-
Save wl00887404/701d2e674babade309dc9d3259ad10b1 to your computer and use it in GitHub Desktop.
This file contains 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 head = ([x, ...xs]) => x | |
const tail = ([_, ...xs]) => xs | |
const last = array => head(array.slice(-1)) | |
const init = array => array.slice(0, -1) | |
const __ = { | |
toString: _ => 'Curry Placeholder' | |
} | |
Object.freeze(__) | |
const curry = func => { | |
const replacePlaceholder = (old, args, acc = []) => { | |
if (old.length == 0) { | |
return [...acc, ...args] | |
} else { | |
const [x, ...xs] = old | |
if (x === __) { | |
const [y, ...ys] = args | |
return replacePlaceholder(xs, ys, [...acc, y]) | |
} else { | |
return replacePlaceholder(xs, args, [...acc, x]) | |
} | |
} | |
} | |
const continueCurry = (old, ...args) => { | |
const now = replacePlaceholder(old, args) | |
const { length } = now.filter(x => x !== __) | |
if (func.length <= length) { | |
return func.apply(null, now) | |
} else { | |
return continueCurry.bind(null, now) | |
} | |
} | |
return continueCurry.bind(null, []) | |
} | |
const zip = curry((array1, array2) => { | |
if (array1.length == 0 || array2.length == 0) { | |
return [] | |
} else { | |
const [x, ...xs] = array1 | |
const [y, ...ys] = array2 | |
return [[x, y], ...zip(xs, ys)] | |
} | |
}) | |
const quickSort = array => { | |
if (array.length < 2) { | |
return array | |
} else { | |
const [x, ...xs] = array | |
const left = xs.filter(el => el < x) | |
const right = xs.filter(el => el >= x) | |
return [...quickSort(left), x, ...quickSort(right)] | |
} | |
} | |
const range = length => Array.from({ length }, (_, i) => i) | |
const repeat = length => x => Array.from({ length }, _ => x) | |
const map = curry((func, array) => { | |
if (array.length == 0) { | |
return [] | |
} else { | |
const [x, ...xs] = array | |
return [func(x), ...map(func, xs)] | |
} | |
}) | |
const filter = curry((func, array) => { | |
if (array.length == 0) { | |
return [] | |
} else { | |
const [x, ...xs] = array | |
const filtered = func(x) ? [x] : [] | |
return [...filtered, ...filter(func, xs)] | |
} | |
}) | |
const reduce = curry((func, acc, array) => { | |
if (array.length == 0) { | |
return acc | |
} else { | |
const [x, ...xs] = array | |
return reduce(func, func(acc, x), xs) | |
} | |
}) | |
const flip = func => curry((y, x, ...args) => func(x, y, ...args)) | |
const max = reduce((acc, el) => (acc > el ? acc : el), -Infinity) | |
const min = reduce((acc, el) => (acc < el ? acc : el), Infinity) | |
const reverse = reduce((acc, el) => [el, ...acc], []) | |
const compose = (...funcs) => | |
(...args) => { | |
const initFuncs = funcs.slice(0, -1) | |
const [lastFunc] = funcs.slice(-1) | |
return initFuncs.reduceRight( | |
(acc, func) => func(acc), | |
lastFunc.apply(null, args) | |
) | |
} | |
const pipe = (...funcs) => | |
(...args) => { | |
const [hFunc, ...tFuncs] = funcs | |
return tFuncs.reduce(( | |
acc, func) => func(acc), | |
hFunc.apply(null, args) | |
) | |
} | |
const composeP = (...funcs) => | |
x => | |
funcs.reduceRight( | |
(acc, func) => acc.then(func), | |
Promise.resolve(x) | |
) | |
class Just { | |
constructor(a) { | |
this._value = a | |
} | |
map(f) { | |
return new Just(f(this._value)) | |
} | |
maybe(n, f) { | |
return f(this._value) | |
} | |
toString() { | |
return `Just ${this._value}` | |
} | |
} | |
class Nothing { | |
constructor() {} | |
map(f) { | |
return new Nothing() | |
} | |
maybe(n, f) { | |
return n | |
} | |
toSting() { | |
return 'Nothing' | |
} | |
} | |
const Maybe = { | |
Nothing: _ => new Nothing(), | |
Just: a => new Just(a), | |
of: a => new Just(a), | |
fromNullable: a => { | |
if (a === null || a === undefined) { | |
return new Nothing() | |
} else { | |
return new Just(a) | |
} | |
} | |
} | |
const safeHead = compose(Maybe.fromNullable, head) | |
class Left { | |
constructor(a) { | |
this._value = a | |
} | |
map(f) { | |
return new Left(this._value) | |
} | |
bimap(f, _) { | |
return new Left(f(this._value)) | |
} | |
either(f, _) { | |
return f(this._value) | |
} | |
toString(){ | |
return `Left ${this._value}` | |
} | |
} | |
class Right { | |
constructor(b) { | |
this._value = b | |
} | |
map(f) { | |
return new Right(f(this._value)) | |
} | |
bimap(_, g) { | |
return new Right(g(this._value)) | |
} | |
either(_, g) { | |
return g(this._value) | |
} | |
toString(){ | |
return `Right ${this._value}` | |
} | |
} | |
const Either = { | |
Left: a => new Left(a), | |
Right: b => new Right(b), | |
of: b => new Right(b) | |
} | |
const tryCatch = f => | |
(...args) => { | |
try { | |
return Either.Right(f.apply(null, args)) | |
} catch (e) { | |
return Either.Left(e) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment