const reduce = f => b => l => {
let r = b
for (let i of l) {
r = f(r)(i)
}
return r
}
const map = f => l => {
return reduce(x => y => x.concat(f(y)))([])(l)
}
const apply = f => x => {
return f(x)
}
const timesapply = n => f => x => {
return reduce(x => y => f(x))(x)(new Array(n).fill(null))
}
const filter = f => l => {
return reduce(x => y => f(y) ? x.concat(y) : x)([])(l)
}
const reject = f => l => {
return reduce(x => y => f(y) ? x : x.concat(y))([])(l)
}
const maths = {
add: x => y => x + y,
sub: x => y => x - y,
mul: x => y => x * y,
div: x => y => x / y,
pow: x => y => x ** y,
mod: x => y => x % y,
abs: x => x >= 0 ? x : -x,
neg: x => -x,
sign: x => x > 0 ? 1 : x === 0 ? 0 :x<0? -1:NaN,
sin: Math.sin,
cos: Math.cos,
tan: Math.tan,
sinh: Math.sinh,
cosh: Math.cosh,
tanh: Math.tanh,
PI:Math.PI
}
const max = l => {
return reduce(x => y => y > x ? y : x)(-Infinity)(l)
}
const min = l => {
return reduce(x => y => y < x ? y : x)(Infinity)(l)
}
const intersection = a => b => {
return reduce(x => y => a.includes(y) ? x.concat(y) : x)([])(b)
}
const union = a => b => {
return reduce(x => y => a.includes(y) ? x : x.concat(y))(a)(b)
}
const complement = a => b => {
return reduce(x => y => b.includes(y) ? x : x.concat(y))([])(a)
}
const distinct = a => {
return reduce(x => y => x.includes(y) ? x : x.concat(y))([])(a)
}
const findif = f => l => {
return reduce(x => y => f(y) || x[0] != -1 ? [y, x[1]] : [x[0], x[1] + 1])([-1, 0])(l)[1]
}
const find = a => l => {
return reduce(x => y => y === a || x[0] != -1 ? [y, x[1]] : [x[0], x[1] + 1])([-1, 0])(l)[1]
}
const reverse = l => {
return reduce(x => y => [y].concat(x))([])(l)
}
const sort = f => l => {
if (l.length < 2) return l
for (let i = 0; i < l.length; i++) {
for (j = 0; j < i; j++) {
if (!f(l[j])(l[i])) {
let t = l[j]
l[j] = l[i]
l[i] = t
}
}
}
return l
}
const pipe = (...fn) => arg => {
return reduce(x => y => y(x))(arg)(fn)
}