|
43 | 43 | // always :: a -> (-> a) |
44 | 44 | var always = function(x) { return function() { return x; }; }; |
45 | 45 |
|
46 | | - // any :: ([a], (a -> Boolean)) -> Boolean |
47 | | - var any = function(xs, pred) { |
48 | | - for (var idx = 0; idx < xs.length; idx += 1) { |
49 | | - if (pred(xs[idx])) return true; |
50 | | - } |
51 | | - return false; |
52 | | - }; |
53 | | - |
54 | 46 | // chain :: ([a], (a -> [b])) -> [b] |
55 | 47 | var chain = function(xs, f) { |
56 | 48 | var result = []; |
|
60 | 52 | return result; |
61 | 53 | }; |
62 | 54 |
|
63 | | - // eqProps :: String -> Object -> Object -> Boolean |
64 | | - var eqProps = function(key) { |
65 | | - return function(o1) { |
66 | | - return function(o2) { |
67 | | - return o1[key] === o2[key]; |
68 | | - }; |
69 | | - }; |
70 | | - }; |
71 | | - |
72 | 55 | // filter :: ([a], (a -> Boolean)) -> [a] |
73 | 56 | var filter = function(xs, pred) { |
74 | 57 | var result = []; |
|
254 | 237 | }; |
255 | 238 | }; |
256 | 239 |
|
257 | | - // Any :: Type |
258 | | - var Any = { |
259 | | - '@@type': 'sanctuary-def/Type', |
260 | | - type: 'ANY', |
261 | | - test: K(true), |
262 | | - toString: always('Any') |
263 | | - }; |
264 | | - |
265 | 240 | // Unknown :: Type |
266 | 241 | var Unknown = { |
267 | 242 | '@@type': 'sanctuary-def/Type', |
|
474 | 449 |
|
475 | 450 | // $.env :: [Type] |
476 | 451 | $.env = [ |
477 | | - ($.Any = Any), |
478 | 452 | ($.Array = type1('Array', id)), |
479 | 453 | ($.Boolean = type0('Boolean')), |
480 | 454 | ($.Date = type0('Date')), |
|
489 | 463 | ($.Undefined = type0('Undefined')) |
490 | 464 | ]; |
491 | 465 |
|
| 466 | + // Any :: Type |
| 467 | + $.Any = NullaryType( |
| 468 | + 'sanctuary-def/Any', |
| 469 | + K(true) |
| 470 | + ); |
| 471 | + |
492 | 472 | // ValidDate :: Type |
493 | 473 | $.ValidDate = NullaryType( |
494 | 474 | 'sanctuary-def/ValidDate', |
|
638 | 618 | } |
639 | 619 | }; |
640 | 620 |
|
641 | | - // rejectAny :: Type -> [Type] |
642 | | - var rejectAny = function recur(t) { |
643 | | - switch (t.type) { |
644 | | - case 'ANY': |
645 | | - return []; |
646 | | - case 'UNARY': |
647 | | - return map(recur(t.$1), UnaryType.from(t)); |
648 | | - case 'BINARY': |
649 | | - return BinaryType.xprod(t, recur(t.$1), recur(t.$2)); |
650 | | - default: |
651 | | - return [t]; |
652 | | - } |
653 | | - }; |
654 | | - |
655 | 621 | // unexpectedType :: Any -> TypeError |
656 | 622 | var unexpectedType = /* istanbul ignore next */ function(x) { |
657 | 623 | return new TypeError( |
|
786 | 752 | ); |
787 | 753 | }; |
788 | 754 |
|
789 | | - var typeNotInEnvironment = function(env, name, type) { |
790 | | - return new TypeError(trimTrailingSpaces(unlines([ |
791 | | - 'Definition of ' + LEFT_SINGLE_QUOTATION_MARK + name + RIGHT_SINGLE_QUOTATION_MARK + |
792 | | - ' references ' + type.name + ' which is not in the environment:', |
793 | | - '', |
794 | | - map(map(chain(env, rejectAny), showType), prefix(' - ')).join('\n') |
795 | | - ]))); |
796 | | - }; |
797 | | - |
798 | 755 | var invalidArgument = function(name, types, value, index) { |
799 | 756 | return new TypeError( |
800 | 757 | LEFT_SINGLE_QUOTATION_MARK + name + RIGHT_SINGLE_QUOTATION_MARK + |
|
1051 | 1008 | x; |
1052 | 1009 | }); |
1053 | 1010 |
|
1054 | | - // assertExpectedTypesInEnvironment :: String -> [Type] -> Undefined |
1055 | | - var assertExpectedTypesInEnvironment = function(name) { |
1056 | | - return function recur(expTypes) { |
1057 | | - for (var idx = 0; idx < expTypes.length; idx += 1) { |
1058 | | - var expType = expTypes[idx]; |
1059 | | - if (expType.type !== 'VARIABLE') { |
1060 | | - if (!any(env, eqProps('name')(expType))) { |
1061 | | - throw typeNotInEnvironment(env, name, expType); |
1062 | | - } |
1063 | | - if (expType.type === 'UNARY') { |
1064 | | - recur([expType.$1]); |
1065 | | - } else if (expType.type === 'BINARY') { |
1066 | | - recur([expType.$1, expType.$2]); |
1067 | | - } |
1068 | | - } |
1069 | | - } |
1070 | | - }; |
1071 | | - }; |
1072 | | - |
1073 | 1011 | // _determineActualTypes :: (Boolean, [Object], [Any]) -> [Type] |
1074 | 1012 | var _determineActualTypes = function recur(loose, $seen, values) { |
1075 | 1013 | if (isEmpty(values)) return [Unknown]; |
1076 | | - // consistentTypes :: [Type] |
1077 | | - var consistentTypes = chain(env, rejectAny); |
1078 | 1014 | // typeses :: [[Type]] |
1079 | 1015 | var typeses = map(values, function(value) { |
1080 | 1016 | if (typeof value === 'object' && value != null || |
|
1084 | 1020 | if ($seen.indexOf(value) >= 0) return []; |
1085 | 1021 | $seen.push(value); |
1086 | 1022 | } |
1087 | | - return chain(consistentTypes, function(t) { |
| 1023 | + return chain(env, function(t) { |
1088 | 1024 | return ( |
1089 | 1025 | t.name === 'sanctuary-def/Nullable' || !test(t, value).valid ? |
1090 | 1026 | [] : |
|
1105 | 1041 | // If none of the values is a member of a type in the environment, |
1106 | 1042 | // and all the values have the same type identifier, the values are |
1107 | 1043 | // members of a "foreign" type. |
1108 | | - if (isEmpty(filterTypesByValues(consistentTypes, values)) && |
| 1044 | + if (isEmpty(filterTypesByValues(env, values)) && |
1109 | 1045 | all(values.slice(1), $$typeEq($$type(values[0])))) { |
1110 | 1046 | // Create a nullary type for the foreign type. |
1111 | 1047 | return [type0($$type(values[0]))]; |
|
1377 | 1313 | ); |
1378 | 1314 | } |
1379 | 1315 |
|
1380 | | - if (checkTypes) assertExpectedTypesInEnvironment(name)(expTypes); |
1381 | | - |
1382 | 1316 | return curry(name, |
1383 | 1317 | constraints, |
1384 | 1318 | expTypes, |
|
0 commit comments