235 lines
3.9 KiB
JavaScript
235 lines
3.9 KiB
JavaScript
"use strict";
|
|
|
|
function variant(tag, value) {
|
|
return value === undefined ? { tag } : { tag, value };
|
|
}
|
|
|
|
function match(value, cases) {
|
|
if (!value || typeof value.tag !== 'string') {
|
|
throw new Error('match: expected variant value');
|
|
}
|
|
const handler = cases[value.tag] || cases._;
|
|
if (!handler) {
|
|
throw new Error(`match: unhandled variant tag: ${value.tag}`);
|
|
}
|
|
return handler(value.value);
|
|
}
|
|
|
|
const nil = [];
|
|
|
|
function cons(head, tail) {
|
|
return [head, ...tail];
|
|
}
|
|
|
|
function head(list) {
|
|
if (list.length === 0) {
|
|
throw new Error('head: empty list');
|
|
}
|
|
return list[0];
|
|
}
|
|
|
|
function tail(list) {
|
|
if (list.length === 0) {
|
|
throw new Error('tail: empty list');
|
|
}
|
|
return list.slice(1);
|
|
}
|
|
|
|
function isEmpty(list) {
|
|
return list.length === 0;
|
|
}
|
|
|
|
function length(list) {
|
|
return list.length;
|
|
}
|
|
|
|
function map(f, list) {
|
|
return list.map(f);
|
|
}
|
|
|
|
function filter(pred, list) {
|
|
return list.filter(pred);
|
|
}
|
|
|
|
function foldl(f, acc, list) {
|
|
return list.reduce(f, acc);
|
|
}
|
|
|
|
function foldr(f, acc, list) {
|
|
return list.reduceRight((acc, x) => f(x, acc), acc);
|
|
}
|
|
|
|
function concat(list1, list2) {
|
|
return [...list1, ...list2];
|
|
}
|
|
|
|
function reverse(list) {
|
|
return list.slice().reverse();
|
|
}
|
|
|
|
function take(n, list) {
|
|
return list.slice(0, n);
|
|
}
|
|
|
|
function drop(n, list) {
|
|
return list.slice(n);
|
|
}
|
|
|
|
const None = variant('None');
|
|
|
|
function Some(value) {
|
|
return variant('Some', value);
|
|
}
|
|
|
|
function isSome(opt) {
|
|
return opt.tag === 'Some';
|
|
}
|
|
|
|
function isNone(opt) {
|
|
return opt.tag === 'None';
|
|
}
|
|
|
|
function unwrap(opt) {
|
|
if (opt.tag === 'None') {
|
|
throw new Error('unwrap: None value');
|
|
}
|
|
return opt.value;
|
|
}
|
|
|
|
function unwrapOr(opt, defaultValue) {
|
|
return opt.tag === 'Some' ? opt.value : defaultValue;
|
|
}
|
|
|
|
function Ok(value) {
|
|
return variant('Ok', value);
|
|
}
|
|
|
|
function Err(error) {
|
|
return variant('Err', error);
|
|
}
|
|
|
|
function isOk(result) {
|
|
return result.tag === 'Ok';
|
|
}
|
|
|
|
function isErr(result) {
|
|
return result.tag === 'Err';
|
|
}
|
|
|
|
function toString(value) {
|
|
if (value === null || value === undefined) {
|
|
return 'null';
|
|
}
|
|
if (Array.isArray(value)) {
|
|
return '[' + value.map(toString).join(', ') + ']';
|
|
}
|
|
if (typeof value === 'object' && value.tag) {
|
|
return value.value === undefined
|
|
? value.tag
|
|
: `${value.tag}(${toString(value.value)})`;
|
|
}
|
|
return String(value);
|
|
}
|
|
|
|
function strLength(str) {
|
|
return str.length;
|
|
}
|
|
|
|
function strConcat(str1, str2) {
|
|
return str1 + str2;
|
|
}
|
|
|
|
function substring(str, start, length) {
|
|
return str.substr(start, length);
|
|
}
|
|
|
|
function intDiv(a, b) {
|
|
return Math.floor(a / b);
|
|
}
|
|
|
|
function pow(base, exp) {
|
|
return Math.pow(base, exp);
|
|
}
|
|
|
|
function abs(x) {
|
|
return Math.abs(x);
|
|
}
|
|
|
|
function print(value) {
|
|
console.log(toString(value));
|
|
}
|
|
|
|
function printStr(value) {
|
|
process.stdout.write(toString(value));
|
|
}
|
|
|
|
function id(x) {
|
|
return x;
|
|
}
|
|
|
|
function constant(x) {
|
|
return () => x;
|
|
}
|
|
|
|
function compose(f, g) {
|
|
return x => f(g(x));
|
|
}
|
|
|
|
function pipe(value, f) {
|
|
return f(value);
|
|
}
|
|
|
|
function curry(f, arity = f.length) {
|
|
return function curried(...args) {
|
|
if (args.length >= arity) {
|
|
return f(...args);
|
|
}
|
|
return (...moreArgs) => curried(...args, ...moreArgs);
|
|
};
|
|
}
|
|
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = {
|
|
variant,
|
|
match,
|
|
nil,
|
|
cons,
|
|
head,
|
|
tail,
|
|
isEmpty,
|
|
length,
|
|
map,
|
|
filter,
|
|
foldl,
|
|
foldr,
|
|
concat,
|
|
reverse,
|
|
take,
|
|
drop,
|
|
None,
|
|
Some,
|
|
isSome,
|
|
isNone,
|
|
unwrap,
|
|
unwrapOr,
|
|
Ok,
|
|
Err,
|
|
isOk,
|
|
isErr,
|
|
toString,
|
|
strLength,
|
|
strConcat,
|
|
substring,
|
|
intDiv,
|
|
pow,
|
|
abs,
|
|
print,
|
|
printStr,
|
|
id,
|
|
constant,
|
|
compose,
|
|
pipe,
|
|
curry
|
|
};
|
|
}
|