Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sanctuary-def

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sanctuary-def - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

834

index.js

@@ -8,3 +8,3 @@ /* global define, self */

/* istanbul ignore else */
if (typeof module !== 'undefined') {
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = f();

@@ -47,10 +47,2 @@ } else if (typeof define === 'function' && define.amd != null) {

// any :: ([a], (a -> Boolean)) -> Boolean
var any = function(xs, pred) {
for (var idx = 0; idx < xs.length; idx += 1) {
if (pred(xs[idx])) return true;
}
return false;
};
// chain :: ([a], (a -> [b])) -> [b]

@@ -65,9 +57,11 @@ var chain = function(xs, f) {

// eqProps :: String -> Object -> Object -> Boolean
var eqProps = function(key) {
return function(o1) {
return function(o2) {
return o1[key] === o2[key];
};
};
// filter :: ([a], (a -> Boolean)) -> [a]
var filter = function(xs, pred) {
var result = [];
for (var idx = 0; idx < xs.length; idx += 1) {
if (pred(xs[idx])) {
result.push(xs[idx]);
}
}
return result;
};

@@ -91,2 +85,5 @@

// last :: [a] -> a
var last = function(xs) { return xs[xs.length - 1]; };
// map :: ([a], (a -> b)) -> [b]

@@ -132,2 +129,46 @@ var map = function(xs, f) {

// reduce :: ([a], b, (b, a) -> b) -> b
var reduce = function(xs, y, f) {
var result = y;
for (var idx = 0; idx < xs.length; idx += 1) result = f(result, xs[idx]);
return result;
};
// strRepeat :: (String, Integer) -> String
var strRepeat = function(s, times) {
return Array(times + 1).join(s);
};
// r :: Char -> String -> String
var r = function(c) {
return function(s) {
return strRepeat(c, s.length);
};
};
// _ :: String -> String
var _ = r(' ');
// toPairs :: StrMap a -> [Pair String a]
var toPairs = function(obj) {
return map(keys(obj), function(k) { return [k, obj[k]]; });
};
// trimTrailingSpaces :: String -> String
var trimTrailingSpaces = function(s) {
return s.replace(/[ ]+$/gm, '');
};
// unlines :: [String] -> String
var unlines = function(lines) {
var s = '';
for (var idx = 0; idx < lines.length; idx += 1) s += lines[idx] + '\n';
return s;
};
// when :: (Boolean, (a -> a), a) -> a
var when = function(bool, f, x) {
return bool ? f(x) : x;
};
// stripNamespace :: String -> String

@@ -204,10 +245,2 @@ var stripNamespace = function(s) { return s.slice(s.indexOf('/') + 1); };

// Any :: Type
var Any = {
'@@type': 'sanctuary-def/Type',
type: 'ANY',
test: K(true),
toString: always('Any')
};
// Unknown :: Type

@@ -221,2 +254,10 @@ var Unknown = {

// Inconsistent :: Type
var Inconsistent = {
'@@type': 'sanctuary-def/Inconsistent',
type: 'INCONSISTENT',
test: K(false),
toString: always('???')
};
// TypeVariable :: String -> Type

@@ -247,2 +288,5 @@ $.TypeVariable = function(name) {

return function($1) {
var format = function(f, f$1) {
return f('(' + stripNamespace(name) + ' ') + f$1(String($1)) + f(')');
};
return {

@@ -252,4 +296,5 @@ '@@type': 'sanctuary-def/Type',

name: name,
test: function(x) { return test(x) && all(_1(x), $1.test); },
toString: always('(' + stripNamespace(name) + ' ' + $1 + ')'),
test: test,
format: format,
toString: always(format(id, id)),
_1: _1,

@@ -261,3 +306,3 @@ $1: $1

// UnaryType.from :: Type -> Type
// UnaryType.from :: Type -> (Type -> Type)
UnaryType.from = function(t) {

@@ -271,2 +316,6 @@ return UnaryType(t.name, t.test, t._1);

return function($1, $2) {
var format = function(f, f$1, f$2) {
return f('(' + stripNamespace(name) + ' ') +
f$1(String($1)) + f(' ') + f$2(String($2)) + f(')');
};
return {

@@ -276,6 +325,5 @@ '@@type': 'sanctuary-def/Type',

name: name,
test: function(x) { return test(x) && all(_1(x), $1.test) &&
all(_2(x), $2.test); },
toString:
always('(' + stripNamespace(name) + ' ' + $1 + ' ' + $2 + ')'),
test: test,
format: format,
toString: always(format(id, id, id)),
_1: _1,

@@ -289,3 +337,3 @@ _2: _2,

// BinaryType.from :: Type -> Type
// BinaryType.from :: Type -> ((Type, Type) -> Type)
BinaryType.from = function(t) {

@@ -337,9 +385,11 @@ return BinaryType(t.name, t.test, t._1, t._2);

if (!isEmpty(invalidMappings)) {
throw new TypeError(
'Invalid values\n\n' +
'The argument to ‘RecordType’ must be an object mapping field name ' +
'to type.\n\n' +
'The following mappings are invalid:\n\n' +
throw new TypeError(trimTrailingSpaces(unlines([
'Invalid values',
'',
'The argument to ‘RecordType’ must be an object mapping field name to type.',
'',
'The following mappings are invalid:',
'',
map(invalidMappings, prefix(' - ')).join('\n')
);
])));
}

@@ -354,3 +404,5 @@

var name = names[idx];
if (!has(name, x) || !fields[name].test(x[name])) return false;
if (!has(name, x) || !test(fields[name], x[name]).valid) {
return false;
}
}

@@ -380,2 +432,11 @@ return true;

// StrMap :: Type -> Type
var StrMap = UnaryType(
'sanctuary-def/StrMap',
function(x) { return $.Object.test(x); },
function(strMap) {
return map(keys(strMap), function(k) { return strMap[k]; });
}
);
// $$type :: a -> String

@@ -407,3 +468,2 @@ var $$type = function(x) {

$.env = [
($.Any = Any),
($.Array = type1('Array', id)),

@@ -418,2 +478,3 @@ ($.Boolean = type0('Boolean')),

($.RegExp = type0('RegExp')),
($.StrMap = StrMap),
($.String = type0('String')),

@@ -423,2 +484,8 @@ ($.Undefined = type0('Undefined'))

// Any :: Type
$.Any = NullaryType(
'sanctuary-def/Any',
K(true)
);
// ValidDate :: Type

@@ -573,38 +640,15 @@ $.ValidDate = NullaryType(

// replaceTypeVars :: {[Type]} -> Type -> [Type]
var replaceTypeVars = function(typeVarMap) {
return function recur(t) {
switch (t.type) {
case 'VARIABLE':
return has(t.name, typeVarMap) ? typeVarMap[t.name] : [t];
case 'UNARY':
return map(recur(t.$1), UnaryType.from(t));
case 'BINARY':
return BinaryType.xprod(t, recur(t.$1), recur(t.$2));
default:
return [t];
}
};
// unexpectedType :: Any -> TypeError
var unexpectedType = /* istanbul ignore next */ function(x) {
return new TypeError(
'Unexpected type ' +
LEFT_SINGLE_QUOTATION_MARK + x + RIGHT_SINGLE_QUOTATION_MARK
);
};
// rejectInconsistent :: Type -> [Type]
var rejectInconsistent = function recur(t) {
switch (t.type) {
case 'ANY':
return [];
case 'UNARY':
return map(recur(t.$1), UnaryType.from(t));
case 'BINARY':
return BinaryType.xprod(t, recur(t.$1), recur(t.$2));
default:
return [t];
}
};
// equalTypes :: (Type, Type) -> Boolean
var equalTypes = function equalTypes(t1, t2) {
// equalTypes :: (Type, Type, Boolean) -> Boolean
var equalTypes = function equalTypes(t1, t2, loose) {
if (t1.type === 'INCONSISTENT' || t2.type === 'INCONSISTENT') return loose;
if (t1.type === 'UNKNOWN' || t2.type === 'UNKNOWN') return true;
switch (t1.type) {
case 'ANY':
return t1.type === t2.type && t1.name === t2.name;
case 'NULLARY':

@@ -614,7 +658,7 @@ return t1.type === t2.type && t1.name === t2.name;

return t1.type === t2.type && t1.name === t2.name &&
equalTypes(t1.$1, t2.$1);
equalTypes(t1.$1, t2.$1, loose);
case 'BINARY':
return t1.type === t2.type && t1.name === t2.name &&
equalTypes(t1.$1, t2.$1) &&
equalTypes(t1.$2, t2.$2);
equalTypes(t1.$1, t2.$1, loose) &&
equalTypes(t1.$2, t2.$2, loose);
case 'ENUM':

@@ -626,25 +670,84 @@ return t1.type === t2.type && show(t1) === show(t2);

default:
throw new TypeError(
'Unexpected type ' +
LEFT_SINGLE_QUOTATION_MARK + t1.type + RIGHT_SINGLE_QUOTATION_MARK
);
throw unexpectedType(t1.type);
}
};
// commonTypes :: [[Type]] -> [Type]
var commonTypes = function(typeses) {
if (isEmpty(typeses)) return [];
// chooseType :: (Type, Type) -> Type
var chooseType = function(t1, t2) {
return t1.type === 'UNKNOWN' ? t2 : t1;
};
return chain(typeses[0], function(t) {
var common = true;
for (var idx = 1; idx < typeses.length; idx += 1) {
common = false;
for (var idx2 = 0; idx2 < typeses[idx].length; idx2 += 1) {
if (equalTypes(t, typeses[idx][idx2])) {
common = true;
break;
}
}
// mergeTypes :: (Type, Type) -> Type
//
// Either String ??? `mergeTypes` Either ??? Number = Either String Number
var mergeTypes = function(t1, t2) {
return (
t1.type === 'UNARY' ?
UnaryType.from(t1)(chooseType(t1.$1, t2.$1)) :
t1.type === 'BINARY' ?
BinaryType.from(t1)(chooseType(t1.$1, t2.$1),
chooseType(t1.$2, t2.$2)) :
// else
chooseType(t1, t2)
);
};
// commonTypes :: ([[Type]], Boolean) -> [Type]
//
// [[String, RegexFlags], [String, RegexFlags]] ---> [String, RegexFlags]
//
// [[Boolean], [Boolean], [Boolean], [Number]] ---> []
//
// [[Array ???], [Array String], [Array ???]] ---> [Array String]
//
// [[Either String ???], [Either ??? Number]] ---> [Either String Number]
var commonTypes = function(typeses, loose) {
return reduce(typeses[0], [], function(types, t) {
var st = reduce(typeses, {ok: true, type: t}, function(st, types) {
var st$ = reduce(types, {ok: false, type: st.type}, function(st, t) {
var equal = equalTypes(st.type, t, loose);
return {ok: equal || st.ok,
type: equal ? mergeTypes(st.type, t) : st.type};
});
return {type: st$.type, ok: st.ok && st$.ok};
});
return st.ok ? types.concat([st.type]) : types;
});
};
// testNested :: (Type, Any, Integer) -> Result
var testNested = function(t, x, position) {
var _ = '_' + String(position);
var $ = '$' + String(position);
for (var idx = 0, xs = t[_](x); idx < xs.length; idx += 1) {
var result = test(t[$], xs[idx]);
if (!result.valid) {
result.typePath.unshift(t);
result.propPath.unshift($);
return result;
}
return common ? [t] : [];
}
return {valid: true, value: x};
};
// test :: (Type, Any) -> Result
var test = function(t, x) {
if (!t.test(x)) {
return {valid: false, value: x, typePath: [t], propPath: []};
} else if (t.type === 'UNARY') {
return testNested(t, x, 1);
} else if (t.type === 'BINARY') {
var lhs = testNested(t, x, 1);
return lhs.valid ? testNested(t, x, 2) : lhs;
} else {
return {valid: true, value: x};
}
};
// filterTypesByValues :: ([Type], [Any]) -> [Type]
var filterTypesByValues = function(types, values) {
return filter(types, function(t) {
return all(values, function(x) {
return test(t, x).valid;
});
});

@@ -674,11 +777,2 @@ };

var typeNotInEnvironment = function(env, name, type) {
return new TypeError(
'Definition of ' + LEFT_SINGLE_QUOTATION_MARK + name +
RIGHT_SINGLE_QUOTATION_MARK + ' references ' + type.name +
' which is not in the environment:\n\n' +
map(chain(env, rejectInconsistent), prefix(' - ')).join('\n')
);
};
var invalidArgument = function(name, types, value, index) {

@@ -692,37 +786,241 @@ return new TypeError(

var orphanArgument = function(env, name, value, index) {
return new TypeError(
LEFT_SINGLE_QUOTATION_MARK + name + RIGHT_SINGLE_QUOTATION_MARK +
' received ' + show(value) + ' as its ' + ordinals[index] +
' argument, but this value is not a member of any of the types ' +
'in the environment:\n\n' +
map(chain(env, rejectInconsistent), prefix(' - ')).join('\n')
);
// constraintsRepr :: StrMap [TypeClass] -> String
var constraintsRepr = function(constraints) {
var reprs = chain(toPairs(constraints), function(pair) {
return map(pair[1], function(typeClass) {
return stripNamespace(typeClass.name) + ' ' + pair[0];
});
});
return when(reprs.length > 0,
function(s) { return s + ' => '; },
when(reprs.length > 1,
function(s) { return '(' + s + ')'; },
reprs.join(', ')));
};
var invalidReturnValue = function(name, types, value) {
return new TypeError(
LEFT_SINGLE_QUOTATION_MARK + name + RIGHT_SINGLE_QUOTATION_MARK +
' is expected to return a value of type ' + types.join(' or ') +
'; returned ' + show(value)
);
// label :: String -> String -> String
var label = function(label) {
return function(s) {
var delta = s.length - label.length;
return strRepeat(' ', Math.floor(delta / 2)) + label +
strRepeat(' ', Math.ceil(delta / 2));
};
};
var invalidValue = function(name, types, value, index) {
return isNaN(index) ?
invalidReturnValue(name, types, value) :
invalidArgument(name, types, value, index);
// arrowJoin :: [String] -> String
var arrowJoin = function(xs) {
return xs.join(' -> ');
};
var constraintViolation = function(name, typeVarName, typeClasses, _types) {
var types = chain(_types, rejectInconsistent);
return new TypeError(
LEFT_SINGLE_QUOTATION_MARK + name + RIGHT_SINGLE_QUOTATION_MARK +
' requires ' + LEFT_SINGLE_QUOTATION_MARK + typeVarName +
RIGHT_SINGLE_QUOTATION_MARK + ' to implement ' +
typeClasses.join(' and ') + '; ' + types.join(' and ') + ' ' +
(types.length === 1 ? 'does' : 'do') + ' not'
// isParameterizedType :: Object -> Boolean
var isParameterizedType = function(t) {
return t.type === 'UNARY' || t.type === 'BINARY';
};
// showType :: Type -> String
var showType = function(t) {
var s = String(t);
return isParameterizedType(t) ? s.slice(1, -1) : s;
};
// showTypeSig :: [Type] -> String
var showTypeSig = function(types) {
return arrowJoin(map(types, showType));
};
// showTypeSig_ :: [Type] -> String
var showTypeSig_ = function(types) {
return arrowJoin(map(types, showType).concat(['']));
};
// _showTypeSig :: [Type] -> String
var _showTypeSig = function(types) {
return arrowJoin([''].concat(map(types, showType)));
};
// _showTypeSig_ :: [Type] -> String
var _showTypeSig_ = function(types) {
return arrowJoin([''].concat(map(types, showType)).concat(['']));
};
// showValueAndType :: Pair Any [Type] -> String
var showValueAndType = function(pair) {
return show(pair[0]) + ' :: ' + map(pair[1], showType).join(', ');
};
// underline :: Type -> [String] -> (String -> String) -> String
var underline = function(type) {
return function(propPath) {
return function(f) {
var t = type;
var types = [t];
for (var idx = 0; idx < propPath.length; idx += 1) {
types.push(t = t[propPath[idx]]);
}
var s = f(String(last(types)));
for (idx = types.length - 2; idx >= 0; idx -= 1) {
t = types[idx];
s = t.type === 'UNARY' ?
t.format(_, K(s)) :
t.type === 'BINARY' && propPath[idx] === '$1' ?
t.format(_, K(s), _) :
// else
t.format(_, _, K(s));
}
return isParameterizedType(type) ? s.slice(1, -1) : s;
};
};
};
// Info = { index :: Integer
// , pairs :: [Pair Any [Type]]
// , propPath :: [String]
// , typePath :: [Type] }
// typeClassConstraintViolation :: ... -> Error
var typeClassConstraintViolation = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
typeClass, // :: TypeClass
info // :: Info
) {
var typeVarName = last(info.typePath).name;
var reprs = chain(toPairs(constraints), function(pair) {
return map(pair[1], function(tc) {
var match = tc.name === typeClass.name && pair[0] === typeVarName;
return r(match ? '^' : ' ')(stripNamespace(tc.name) + ' ' + pair[0]);
});
});
var carets = when(reprs.length > 1,
function(s) { return _('(') + s + _(')'); },
reprs.join(_(', ')));
var padding = _(showTypeSig_(expTypes.slice(0, info.index)));
var f = underline(info.typePath[0])(info.propPath);
return new TypeError(trimTrailingSpaces(unlines([
'Type-class constraint violation',
'',
name + ' :: ' + constraintsRepr(constraints) + showTypeSig(expTypes),
_(name + ' :: ') + carets + _(' => ') + padding + f(r('^')),
_(name + ' :: ' + carets + ' => ') + padding + f(label('1')),
'',
'1) ' + map(info.pairs, showValueAndType).join('\n '),
'',
LEFT_SINGLE_QUOTATION_MARK + name + RIGHT_SINGLE_QUOTATION_MARK + ' requires ' +
LEFT_SINGLE_QUOTATION_MARK + typeVarName + RIGHT_SINGLE_QUOTATION_MARK +
' to satisfy the ' + typeClass + ' type-class constraint;' +
' the value at position 1 does not.'
])));
};
// annotateSig :: ... -> String
var annotateSig = function(
types, // :: [Type]
fst, // :: Info
snd, // :: Info
f, // :: String -> String
g // :: String -> String
) {
return _(_showTypeSig((types.slice(0, fst.index)))) +
underline(fst.typePath[0])(fst.propPath)(f) +
_(_showTypeSig_(types.slice(fst.index + 1, snd.index))) +
underline(snd.typePath[0])(snd.propPath)(g);
};
// _typeVarConstraintViolation :: ... -> Error
var _typeVarConstraintViolation = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
carets, // :: String
numbers, // :: String
pairss // :: [[Pair Any [Type]]]
) {
var nameAndConstraints = name + ' :: ' + constraintsRepr(constraints);
var lines = [];
lines.push('Type-variable constraint violation');
lines.push('');
lines.push(nameAndConstraints + showTypeSig(expTypes));
lines.push(_(nameAndConstraints) + carets);
lines.push(_(nameAndConstraints) + numbers);
for (var idx = 0; idx < pairss.length; idx += 1) {
lines.push('');
lines.push(String(idx + 1) + ') ' +
map(pairss[idx], showValueAndType).join('\n '));
}
lines.push('');
lines.push('Since there is no type of which all the above values are ' +
'members, the type-variable constraint has been violated.');
return new TypeError(trimTrailingSpaces(unlines(lines)));
};
// typeVarConstraintViolation :: ... -> Error
var typeVarConstraintViolation = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
info // :: Info
) {
var padding = _(_showTypeSig(expTypes.slice(0, info.index)));
var f = underline(expTypes[info.index])(info.propPath);
return _typeVarConstraintViolation(
name,
constraints,
expTypes,
padding + f(r('^')),
padding + f(label('1')),
[info.pairs]
);
};
// typeVarConstraintViolation2 :: ... -> Error
var typeVarConstraintViolation2 = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
_fst, // :: Info
_snd // :: Info
) {
var fst = _fst.index < _snd.index ? _fst : _snd;
var snd = _fst.index < _snd.index ? _snd : _fst;
return _typeVarConstraintViolation(
name,
constraints,
expTypes,
annotateSig(expTypes, fst, snd, r('^'), r('^')),
annotateSig(expTypes, fst, snd, label('1'), label('2')),
[fst.pairs, snd.pairs]
);
};
// invalidValue :: ... -> Error
var invalidValue = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
info // :: Info
) {
var nameAndConstraints = name + ' :: ' + constraintsRepr(constraints);
var padding = _(_showTypeSig(expTypes.slice(0, info.index)));
var f = underline(info.typePath[0])(info.propPath);
return new TypeError(trimTrailingSpaces(unlines([
'Invalid value',
'',
nameAndConstraints + showTypeSig(expTypes),
_(nameAndConstraints) + padding + f(r('^')),
_(nameAndConstraints) + padding + f(label('1')),
'',
'1) ' + map(info.pairs, showValueAndType).join('\n '),
'',
'The value at position 1 is not a member of ' +
LEFT_SINGLE_QUOTATION_MARK + showType(last(info.typePath)) + RIGHT_SINGLE_QUOTATION_MARK + '.'
])));
};
// create :: (Boolean, [Type]) -> Function

@@ -737,47 +1035,85 @@ $.create = function(checkTypes, _env) {

// assertExpectedTypesInEnvironment :: String -> [Type] -> Undefined
var assertExpectedTypesInEnvironment = function(name) {
return function recur(expTypes) {
for (var idx = 0; idx < expTypes.length; idx += 1) {
var expType = expTypes[idx];
if (expType.type !== 'VARIABLE') {
if (!any(env, eqProps('name')(expType))) {
throw typeNotInEnvironment(env, name, expType);
}
if (expType.type === 'UNARY') {
recur([expType.$1]);
} else if (expType.type === 'BINARY') {
recur([expType.$1, expType.$2]);
}
}
// _determineActualTypes :: (Boolean, [Object], [Any]) -> [Type]
var _determineActualTypes = function recur(loose, seen, values) {
if (isEmpty(values)) return [Unknown];
// typeses :: [[Type]]
var typeses = map(values, function(value) {
var seen$;
if (typeof value === 'object' && value != null ||
typeof value === 'function') {
// Abort if a circular reference is encountered; add the current
// object to the list of seen objects otherwise.
if (seen.indexOf(value) >= 0) return [];
seen$ = seen.concat([value]);
} else {
seen$ = seen;
}
};
return chain(env, function(t) {
return (
t.name === 'sanctuary-def/Nullable' || !test(t, value).valid ?
[] :
t.type === 'UNARY' ?
map(recur(loose, seen$, t._1(value)), UnaryType.from(t)) :
t.type === 'BINARY' ?
BinaryType.xprod(t,
recur(loose, seen$, t._1(value)),
recur(loose, seen$, t._2(value))) :
// else
[t]
);
});
});
// common :: [Type]
var common = commonTypes(typeses, loose);
if (!isEmpty(common)) return common;
// If none of the values is a member of a type in the environment,
// and all the values have the same type identifier, the values are
// members of a "foreign" type.
if (isEmpty(filterTypesByValues(env, values)) &&
all(values.slice(1), $$typeEq($$type(values[0])))) {
// Create a nullary type for the foreign type.
return [type0($$type(values[0]))];
}
return [Inconsistent];
};
// determineActualTypes :: a -> [Type]
var determineActualTypes = function recur(value) {
return chain(env, function(t) {
return (
t.name === 'sanctuary-def/Nullable' || !t.test(value) ?
[] :
t.type === 'UNARY' ?
map(commonTypes(or(map(t._1(value), recur), [[Unknown]])),
UnaryType.from(t)) :
t.type === 'BINARY' ?
BinaryType.xprod(
t,
commonTypes(or(map(t._1(value), recur), [[Unknown]])),
commonTypes(or(map(t._2(value), recur), [[Unknown]]))
) :
// else
[t]
);
// rejectInconsistent :: [Type] -> [Type]
var rejectInconsistent = function(types) {
return filter(types, function(t) {
return t.type !== 'INCONSISTENT' && t.type !== 'UNKNOWN';
});
};
var _satisfactoryTypes =
function(name, constraints, $typeVarMap, _value, index) {
return function recur(expType, values, nest) {
// determineActualTypesStrict :: [Any] -> [Type]
var determineActualTypesStrict = function(values) {
return rejectInconsistent(_determineActualTypes(false, [], values));
};
// determineActualTypesLoose :: [Any] -> [Type]
var determineActualTypesLoose = function(values) {
return rejectInconsistent(_determineActualTypes(true, [], values));
};
// valuesToPairs :: [Any] -> [Pair Any [Type]]
var valuesToPairs = function(values) {
return map(values, function(x) {
return [x, determineActualTypesLoose([x])];
});
};
// _satisfactoryTypes :: ... -> [Type]
var _satisfactoryTypes = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
$typeVarMap, // :: StrMap { info :: Info, types :: [Type] }
index // :: Integer
) {
return function recur(
expType, // :: Type
values, // :: [Any]
typePath, // :: [Type]
propPath // :: [String]
) {
var $1s, $2s, idx, okTypes;
switch (expType.type) {

@@ -792,7 +1128,11 @@

if (!typeClasses[idx2].test(values[idx])) {
throw constraintViolation(
throw typeClassConstraintViolation(
name,
typeVarName,
typeClasses,
commonTypes(map(values, determineActualTypes))
constraints,
expTypes,
typeClasses[idx2],
{index: index,
pairs: valuesToPairs([values[idx]]),
propPath: propPath,
typePath: typePath.concat([expType])}
);

@@ -804,17 +1144,41 @@ }

if (has(typeVarName, $typeVarMap)) {
var types = $typeVarMap[typeVarName];
okTypes = chain(types, function(t) {
return all(values, t.test) ? [t] : [];
});
okTypes = filterTypesByValues($typeVarMap[typeVarName].types,
values);
if (isEmpty(okTypes)) {
throw invalidValue(name, map(types, nest), _value, index);
throw typeVarConstraintViolation2(
name,
constraints,
expTypes,
{index: index,
pairs: valuesToPairs(values),
propPath: propPath,
typePath: typePath.concat([expType])},
$typeVarMap[typeVarName].info
);
}
} else {
okTypes = chain(commonTypes(map(values, determineActualTypes)),
rejectInconsistent);
okTypes = determineActualTypesStrict(values);
if (isEmpty(okTypes) && !isEmpty(values)) {
throw orphanArgument(env, name, _value, index);
throw typeVarConstraintViolation(
name,
constraints,
expTypes,
{index: index,
pairs: valuesToPairs(values),
propPath: propPath,
typePath: typePath.concat([expType])}
);
}
}
if (!isEmpty(okTypes)) $typeVarMap[typeVarName] = okTypes;
if (!isEmpty(okTypes)) {
$typeVarMap[typeVarName] = {
types: okTypes,
info: {
index: index,
pairs: valuesToPairs(values),
propPath: propPath,
typePath: typePath.concat([expType])
}
};
}
return okTypes;

@@ -825,13 +1189,15 @@

chain(values, expType._1),
UnaryType.from(expType));
typePath.concat([expType]),
propPath.concat(['$1']));
return map(or($1s, [expType.$1]), UnaryType.from(expType));
case 'BINARY':
var specialize = BinaryType.from(expType);
$1s = recur(expType.$1,
chain(values, expType._1),
function($1) { return specialize($1, expType.$2); });
typePath.concat([expType]),
propPath.concat(['$1']));
$2s = recur(expType.$2,
chain(values, expType._2),
function($2) { return specialize(expType.$1, $2); });
typePath.concat([expType]),
propPath.concat(['$2']));
return BinaryType.xprod(expType,

@@ -842,3 +1208,3 @@ or($1s, [expType.$1]),

default:
return commonTypes(map(values, determineActualTypes));
return determineActualTypesStrict(values);
}

@@ -848,11 +1214,34 @@ };

var satisfactoryTypes =
function(name, constraints, $typeVarMap, expType, value, index) {
return _satisfactoryTypes(name, constraints, $typeVarMap, value, index)
(expType, [value], id);
// satisfactoryTypes :: ... -> [Type]
var satisfactoryTypes = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
$typeVarMap, // :: StrMap { info :: Info, types :: [Type] }
value, // :: Any
index // :: Integer
) {
return _satisfactoryTypes(name,
constraints,
expTypes,
$typeVarMap,
index)
(expTypes[index],
[value],
[],
[]);
};
var curry = function(name, constraints, expArgTypes, expRetType,
_typeVarMap, _values, _indexes, impl) {
// curry :: ... -> Function
var curry = function(
name, // :: String
constraints, // :: StrMap [TypeClass]
expTypes, // :: [Type]
_typeVarMap, // :: StrMap { info :: Info, types :: [Type] }
_values, // :: [Any]
_indexes, // :: [Integer]
impl // :: Function
) {
return arity(_indexes.length, function() {
var result;
if (checkTypes) {

@@ -862,4 +1251,4 @@ var delta = _indexes.length - arguments.length;

throw invalidArgumentsLength(name,
expArgTypes.length,
expArgTypes.length - delta);
expTypes.length - 1,
expTypes.length - 1 - delta);
}

@@ -869,3 +1258,3 @@ }

for (var typeVarName in _typeVarMap) {
$typeVarMap[typeVarName] = _typeVarMap[typeVarName].slice();
$typeVarMap[typeVarName] = _typeVarMap[typeVarName];
}

@@ -884,11 +1273,18 @@ var values = _values.slice();

if (checkTypes) {
var expType = expArgTypes[index];
if (!expType.test(value) ||
isEmpty(satisfactoryTypes(name, constraints, $typeVarMap,
expType, value, index))) {
result = test(expTypes[index], value);
if (!result.valid) {
throw invalidValue(name,
replaceTypeVars($typeVarMap)(expType),
value,
index);
constraints,
expTypes,
{index: index,
pairs: valuesToPairs([result.value]),
propPath: result.propPath,
typePath: result.typePath});
}
satisfactoryTypes(name,
constraints,
expTypes,
$typeVarMap,
value,
index);
}

@@ -903,12 +1299,28 @@ values[index] = value;

if (checkTypes) {
if (!expRetType.test(returnValue)) {
throw invalidReturnValue(name, [expRetType], returnValue);
result = test(last(expTypes), returnValue);
if (!result.valid) {
throw invalidValue(name,
constraints,
expTypes,
{index: _indexes.length,
pairs: valuesToPairs([result.value]),
propPath: result.propPath,
typePath: result.typePath});
}
satisfactoryTypes(name, constraints, $typeVarMap,
expRetType, returnValue, NaN);
satisfactoryTypes(name,
constraints,
expTypes,
$typeVarMap,
returnValue,
expTypes.length - 1);
}
return returnValue;
} else {
return curry(name, constraints, expArgTypes, expRetType,
$typeVarMap, values, indexes, impl);
return curry(name,
constraints,
expTypes,
$typeVarMap,
values,
indexes,
impl);
}

@@ -927,3 +1339,3 @@ });

for (var idx = 0; idx < types.length; idx += 1) {
if (!types[idx].test(arguments[idx])) {
if (!test(types[idx], arguments[idx]).valid) {
throw invalidArgument('def', [types[idx]], arguments[idx], idx);

@@ -934,4 +1346,3 @@ }

var expArgTypes = expTypes.slice(0, -1);
var arity = expArgTypes.length;
var arity = expTypes.length - 1;
if (arity > 9) {

@@ -944,8 +1355,5 @@ throw new RangeError(

if (checkTypes) assertExpectedTypesInEnvironment(name)(expTypes);
return curry(name,
constraints,
expArgTypes,
expTypes[expTypes.length - 1],
expTypes,
{},

@@ -952,0 +1360,0 @@ new Array(arity),

{
"name": "sanctuary-def",
"version": "0.4.0",
"version": "0.5.0",
"description": "Run-time type system for JavaScript",

@@ -19,3 +19,3 @@ "license": "MIT",

"mocha": "2.x.x",
"ramda": "~0.19.1",
"ramda": "0.21.x",
"xyz": "0.5.x"

@@ -22,0 +22,0 @@ },

@@ -124,3 +124,11 @@ # sanctuary-def

add('2', '2');
// ! TypeError: ‘add’ expected a value of type Number as its first argument; received "2"
// ! TypeError: Invalid value
//
// add :: Number -> Number -> Number
// ^^^^^^
// 1
//
// 1) "2" :: String
//
// The value at position 1 is not a member of ‘Number’.
```

@@ -133,3 +141,11 @@

add('X');
// ! TypeError: ‘add’ expected a value of type Number as its first argument; received "X"
// ! TypeError: Invalid value
//
// add :: Number -> Number -> Number
// ^^^^^^
// 1
//
// 1) "X" :: String
//
// The value at position 1 is not a member of ‘Number’.
```

@@ -346,2 +362,13 @@

#### `StrMap`
```haskell
$.StrMap :: Type -> Type
```
Constructor for homogeneous Object types.
`{foo: 1, bar: 2, baz: 3}`, for example, is a member of `StrMap Number`;
`{foo: 1, bar: 2, baz: 'XXX'}` is not.
#### `String`

@@ -384,3 +411,2 @@

- [`$.Any`](#any)
- [`$.Array`](#array)

@@ -395,2 +421,3 @@ - [`$.Boolean`](#boolean)

- [`$.RegExp`](#regexp)
- [`$.StrMap`](#strmap)
- [`$.String`](#string)

@@ -447,3 +474,13 @@ - [`$.Undefined`](#undefined)

cmp(0, '1');
// ! TypeError: ‘cmp’ expected a value of type Number as its second argument; received "1"
// ! TypeError: Type-variable constraint violation
//
// cmp :: a -> a -> Number
// ^ ^
// 1 2
//
// 1) 0 :: Number
//
// 2) "1" :: String
//
// Since there is no type of which all the above values are members, the type-variable constraint has been violated.
```

@@ -494,6 +531,22 @@

rem(0.5);
// ! TypeError: ‘rem’ expected a value of type Integer as its first argument; received 0.5
// ! TypeError: Invalid value
//
// rem :: Integer -> NonZeroInteger -> Integer
// ^^^^^^^
// 1
//
// 1) 0.5 :: Number
//
// The value at position 1 is not a member of ‘Integer’.
rem(42, 0);
// ! TypeError: ‘rem’ expected a value of type NonZeroInteger as its second argument; received 0
// ! TypeError: Invalid value
//
// rem :: Integer -> NonZeroInteger -> Integer
// ^^^^^^^^^^^^^^
// 1
//
// 1) 0 :: Number
//
// The value at position 1 is not a member of ‘NonZeroInteger’.
```

@@ -515,3 +568,11 @@

sum(['1', '2', '3', '4']);
// ! TypeError: ‘sum’ expected a value of type (Array Number) as its first argument; received ["1", "2", "3", "4"]
// ! TypeError: Invalid value
//
// sum :: Array Number -> Number
// ^^^^^^
// 1
//
// 1) "1" :: String
//
// The value at position 1 is not a member of ‘Number’.
```

@@ -574,3 +635,13 @@

fromMaybe(0, Just('XXX'));
// ! TypeError: ‘fromMaybe’ expected a value of type (Maybe Number) as its second argument; received Just("XXX")
// ! TypeError: Type-variable constraint violation
//
// fromMaybe :: a -> Maybe a -> a
// ^ ^
// 1 2
//
// 1) 0 :: Number
//
// 2) "XXX" :: String
//
// Since there is no type of which all the above values are members, the type-variable constraint has been violated.
```

@@ -649,3 +720,11 @@

showCard(Pair('X', '♠'));
// ! TypeError: ‘showCard’ expected a value of type (Pair Rank Suit) as its first argument; received Pair("X", "♠")
// ! TypeError: Invalid value
//
// showCard :: Pair Rank Suit -> String
// ^^^^
// 1
//
// 1) "X" :: String
//
// The value at position 1 is not a member of ‘Rank’.
```

@@ -671,7 +750,2 @@

// env :: [Type]
const env = $.env.concat([TimeUnit, $.ValidDate, $.ValidNumber]);
const def = $.create(true, env);
// convertTo :: TimeUnit -> ValidDate -> ValidNumber

@@ -695,3 +769,11 @@ const convertTo =

convertTo('days', new Date(1000));
// ! TypeError: ‘convertTo’ expected a value of type ("milliseconds" | "seconds" | "minutes" | "hours") as its first argument; received "days"
// ! TypeError: Invalid value
//
// convertTo :: ("milliseconds" | "seconds" | "minutes" | "hours") -> ValidDate -> ValidNumber
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 1
//
// 1) "days" :: String
//
// The value at position 1 is not a member of ‘("milliseconds" | "seconds" | "minutes" | "hours")’.
```

@@ -715,14 +797,8 @@

```javascript
// FiniteNumber :: Type
const FiniteNumber = $.NullaryType(
'my-package/FiniteNumber',
x => Object.prototype.toString.call(x) === '[object Number]' && isFinite(x)
);
// Point :: Type
const Point = $.RecordType({x: FiniteNumber, y: FiniteNumber});
const Point = $.RecordType({x: $.FiniteNumber, y: $.FiniteNumber});
// dist :: Point -> Point -> FiniteNumber
const dist =
def('dist', {}, [Point, Point, FiniteNumber],
def('dist', {}, [Point, Point, $.FiniteNumber],
(p, q) => Math.sqrt(Math.pow(p.x - q.x, 2) + Math.pow(p.y - q.y, 2)));

@@ -737,6 +813,22 @@

dist({x: 0, y: 0}, {x: NaN, y: NaN});
// ! TypeError: ‘dist’ expected a value of type { x :: FiniteNumber, y :: FiniteNumber } as its second argument; received {"x": NaN, "y": NaN}
// ! TypeError: Invalid value
//
// dist :: { x :: FiniteNumber, y :: FiniteNumber } -> { x :: FiniteNumber, y :: FiniteNumber } -> FiniteNumber
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 1
//
// 1) {"x": NaN, "y": NaN} :: Object, StrMap Number
//
// The value at position 1 is not a member of ‘{ x :: FiniteNumber, y :: FiniteNumber }’.
dist(0);
// ! TypeError: ‘dist’ expected a value of type { x :: FiniteNumber, y :: FiniteNumber } as its first argument; received 0
// ! TypeError: Invalid value
//
// dist :: { x :: FiniteNumber, y :: FiniteNumber } -> { x :: FiniteNumber, y :: FiniteNumber } -> FiniteNumber
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 1
//
// 1) 0 :: Number
//
// The value at position 1 is not a member of ‘{ x :: FiniteNumber, y :: FiniteNumber }’.
```

@@ -764,3 +856,13 @@

_concat([1, 2], 'buzz');
// ! TypeError: ‘_concat’ expected a value of type (Array Number) as its second argument; received "buzz"
// ! TypeError: Type-variable constraint violation
//
// _concat :: a -> a -> a
// ^ ^
// 1 2
//
// 1) [1, 2] :: Array Number
//
// 2) "buzz" :: String
//
// Since there is no type of which all the above values are members, the type-variable constraint has been violated.
```

@@ -800,6 +902,22 @@

concat({}, {});
// ! TypeError: ‘concat’ requires ‘a’ to implement Semigroup; Object does not
// ! TypeError: Type-class constraint violation
//
// concat :: Semigroup a => a -> a -> a
// ^^^^^^^^^^^ ^
// 1
//
// 1) {} :: Object, StrMap ???
//
// ‘concat’ requires ‘a’ to satisfy the Semigroup type-class constraint; the value at position 1 does not.
concat(null, null);
// ! TypeError: ‘concat’ requires ‘a’ to implement Semigroup; Null does not
// ! TypeError: Type-class constraint violation
//
// concat :: Semigroup a => a -> a -> a
// ^^^^^^^^^^^ ^
// 1
//
// 1) null :: Null
//
// ‘concat’ requires ‘a’ to satisfy the Semigroup type-class constraint; the value at position 1 does not.
```

@@ -806,0 +924,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc