wecui
Version:
一款基于Vue2.x版本的移动端web组件
114 lines (87 loc) • 3.65 kB
JavaScript
var assert = require('./assert');
var isTypeName = require('./isTypeName');
var FunctionType = require('./Function');
var isArray = require('./isArray');
var list = require('./list');
var isObject = require('./isObject');
var create = require('./create');
var isNil = require('./isNil');
var isBoolean = require('./isBoolean');
var tuple = require('./tuple');
var getFunctionName = require('./getFunctionName');
var getTypeName = require('./getTypeName');
function getDefaultName(domain, codomain) {
return '(' + domain.map(getTypeName).join(', ') + ') => ' + getTypeName(codomain);
}
function isInstrumented(f) {
return FunctionType.is(f) && isObject(f.instrumentation);
}
function func(domain, codomain, name) {
domain = isArray(domain) ? domain : [domain]; // handle handy syntax for unary functions
if (process.env.NODE_ENV !== 'production') {
assert(list(FunctionType).is(domain), function () { return 'Invalid argument domain ' + assert.stringify(domain) + ' supplied to func(domain, codomain, [name]) combinator (expected an array of types)'; });
assert(FunctionType.is(codomain), function () { return 'Invalid argument codomain ' + assert.stringify(codomain) + ' supplied to func(domain, codomain, [name]) combinator (expected a type)'; });
assert(isTypeName(name), function () { return 'Invalid argument name ' + assert.stringify(name) + ' supplied to func(domain, codomain, [name]) combinator (expected a string)'; });
}
var displayName = name || getDefaultName(domain, codomain);
function FuncType(value, curried) {
if (!isInstrumented(value)) { // automatically instrument the function
return FuncType.of(value, curried);
}
if (process.env.NODE_ENV !== 'production') {
assert(FuncType.is(value), function () { return 'Invalid value ' + assert.stringify(value) + ' supplied to ' + displayName; });
}
return value;
}
FuncType.meta = {
kind: 'func',
domain: domain,
codomain: codomain,
name: name,
identity: true
};
FuncType.displayName = displayName;
FuncType.is = function (x) {
return isInstrumented(x) &&
x.instrumentation.domain.length === domain.length &&
x.instrumentation.domain.every(function (type, i) {
return type === domain[i];
}) &&
x.instrumentation.codomain === codomain;
};
FuncType.of = function (f, curried) {
if (process.env.NODE_ENV !== 'production') {
assert(FunctionType.is(f), function () { return 'Invalid argument f supplied to func.of ' + displayName + ' (expected a function)'; });
assert(isNil(curried) || isBoolean(curried), function () { return 'Invalid argument curried ' + assert.stringify(curried) + ' supplied to func.of ' + displayName + ' (expected a boolean)'; });
}
if (FuncType.is(f)) { // makes FuncType.of idempotent
return f;
}
function fn() {
var args = Array.prototype.slice.call(arguments);
var len = curried ?
args.length :
domain.length;
var argsType = tuple(domain.slice(0, len));
args = argsType(args); // type check arguments
if (len === domain.length) {
return create(codomain, f.apply(this, args));
}
else {
var g = Function.prototype.bind.apply(f, [this].concat(args));
var newdomain = func(domain.slice(len), codomain);
return newdomain.of(g, curried);
}
}
fn.instrumentation = {
domain: domain,
codomain: codomain,
f: f
};
fn.displayName = getFunctionName(f);
return fn;
};
return FuncType;
}
func.getDefaultName = getDefaultName;
module.exports = func;