diff --git a/package.json b/package.json index a17d45f..6fdaa0f 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "fantasy-land": "^3.5.0", "hm-parser": "^0.1.5", "mem": "^4.0.0", - "sanctuary": "^0.15.0", - "sanctuary-def": "^0.18.1", + "sanctuary": "^2.0.1", + "sanctuary-def": "^0.20.1", "sanctuary-show": "^1.0.0" }, "devDependencies": { @@ -41,7 +41,7 @@ "jsverify": "^0.8.3", "mocha": "^5.2.0", "sanctuary-style": "^2.0.0", - "sanctuary-type-classes": "^9.0.0", + "sanctuary-type-classes": "^11.0.0", "xyz": "3.0.x" } } diff --git a/src/signature.js b/src/signature.js index 4a1ef6a..cf06463 100644 --- a/src/signature.js +++ b/src/signature.js @@ -189,16 +189,18 @@ export const resolve = $ => { const fromUnaryType = t => $.UnaryType (t.name) (t.url) - (t._test) - (t.types.$1.extractor); + (t.supertypes) + (t._test ([])) + (t.extractors.$1); // fromBinaryType :: Type -> (Type -> Type -> Type) const fromBinaryType = t => $.BinaryType (t.name) (t.url) - (t._test) - (t.types.$1.extractor) - (t.types.$2.extractor); + (t.supertypes) + (t._test ([])) + (t.extractors.$1) + (t.extractors.$2); // constructType :: (Array Type) -> Type -> Type const constructType = argTypes => t => { @@ -217,7 +219,7 @@ export const resolve = $ => { }; // Helper Type to wipe out thunks - const Thunk = $.NullaryType ('hm-def/Thunk') ('') (S.K (false)); + const Thunk = $.NullaryType ('hm-def/Thunk') ('') ([]) (S.K (false)); // convertType :: SignatureEntry -> Reader (TypeMap Type) const convertType = memoize (entry => cond ([ diff --git a/test/def.spec.js b/test/def.spec.js index 030321a..944c441 100644 --- a/test/def.spec.js +++ b/test/def.spec.js @@ -4,11 +4,10 @@ import Z from 'sanctuary-type-classes'; import {assert} from 'chai'; import {create} from '../src/index'; -const hasProp = p => x => x[p] !== undefined; - const $Map = $.BinaryType ('Map') ('someurl') + ([]) (S.is ($.Object)) (S.keys) (S.values); @@ -16,7 +15,8 @@ const $Map = $.BinaryType const $Wrapper = $.UnaryType ('Wrapper') ('someurl') - (S.allPass ([S.is ($.Object), hasProp ('value')])) + ([$.Object]) + (x => 'value' in x) (S.pipe ([S.prop ('value'), S.of (Array)])); const def = create ({ @@ -66,7 +66,7 @@ describe ('def', () => { const cube = x => x * x * x; assert.deepEqual (foo (cube) ([1, 2, 3]), [1, 8, 27]); - assert.throws (() => foo (cube) ('im-not-an-unary-type'), 'Type-class constraint violation'); + assert.throws (() => foo (cube) ('im-not-an-unary-type'), 'The value at position 1 is not a member of ‘f a’'); }); it ('should work with type class constraints', () => { diff --git a/test/signature.spec.js b/test/signature.spec.js index 28b445f..727106a 100644 --- a/test/signature.spec.js +++ b/test/signature.spec.js @@ -1,25 +1,18 @@ import S from 'sanctuary'; import $ from 'sanctuary-def'; import Z from 'sanctuary-type-classes'; +import show from 'sanctuary-show'; import {assert} from 'chai'; import {resolve} from '../src/signature'; -// assertSameType :: Type -> Type -> Undefined ! -const assertSameType = actual => expected => { - assert.strictEqual (actual.name, expected.name); - assert.strictEqual (actual.type, expected.type); - assert.deepEqual (actual.keys, expected.keys); - assert.deepEqual (actual.url, expected.url); - expected.keys.forEach (key => { - assertSameType (actual.types[key].type) (expected.types[key].type); - }); +// assertSameTypes :: [Type] -> [Type] -> Undefined ! +const assertSameTypes = actual => expected => { + if (!(S.equals (actual) (expected))) { // Array and Type are both Setoid providing equals() + assert.equal (show (actual), show (expected), 'S.equals'); // assert.equal() because assert.isOk() does not diff actual/expected + assert.fail (); // final failure in the hypothetical case that show() would return same strings for different types + } }; -const assertTypePairs = xs => xs.forEach - (pair => assertSameType - (S.fst (pair)) - (S.snd (pair))); - describe ('Function name', () => { it ('should be extracted', () => { const {name} = resolve ($) ([]) ($.env) ('foo :: Number -> Number'); @@ -59,14 +52,14 @@ describe ('Parameter types', () => { }); it ('should resolve user types', () => { - const Widget = $.NullaryType ('Widget') ('http://example.com/Widget') (S.K (true)); + const Widget = $.NullaryType ('Widget') ('http://example.com/Widget') ([]) (S.K (true)); const env = $.env.concat ([Widget]); const {types} = resolve ($) ([]) (env) ('foo :: Widget -> String'); assert.deepEqual (types, [Widget, $.String]); }); it ('should resolve namespaced user types', () => { - const Widget = $.NullaryType ('x/y/z/Widget') ('http://example.com/Widget') (S.K (true)); + const Widget = $.NullaryType ('x/y/z/Widget') ('http://example.com/Widget') ([]) (S.K (true)); const env = $.env.concat ([Widget]); const {types} = resolve ($) ([]) (env) ('foo :: Widget -> String'); assert.deepEqual (types, [Widget, $.String]); @@ -74,27 +67,22 @@ describe ('Parameter types', () => { it ('should resolve lists', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: [Number] -> [String]'); - const expecteds = [$.Array ($.Number), $.Array ($.String)]; - - const lists = S.zip (types) (expecteds); - assertTypePairs (lists); + assertSameTypes (types) ([$.Array ($.Number), $.Array ($.String)]); }); it ('should resolve functions', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: Number -> (Number -> Number)'); - const lists = S.zip (types) ([$.Number, $.Function ([$.Number, $.Number])]); - assertTypePairs (lists); + assertSameTypes (types) ([$.Number, $.Function ([$.Number, $.Number])]); }); it ('should resolve functions that return multi-arity functions', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: Number -> (Number -> Number -> Number)'); - const lists = S.zip (types) ([$.Number, $.Function ([$.Number, $.Function ([$.Number, $.Number])])]); - assertTypePairs (lists); + assertSameTypes (types) ([$.Number, $.Function ([$.Number, $.Function ([$.Number, $.Number])])]); }); it ('should resolve higher-order functions that take multi-arity functions', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: (Number -> Number -> Number) -> Number'); - const lists = S.zip (types) ([ + const expecteds = [ $.Function ([ $.Number, $.Function ([ @@ -103,14 +91,13 @@ describe ('Parameter types', () => { ]), ]), $.Number, - ]); - assertTypePairs (lists); + ]; + assertSameTypes (types) (expecteds); }); it ('should resolve unary types', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: Number -> StrMap Number'); - const lists = S.zip (types) ([$.Number, $.StrMap ($.Number)]); - assertTypePairs (lists); + assertSameTypes (types) ([$.Number, $.StrMap ($.Number)]); }); it ('should bark on wrong number of arguments', () => { @@ -136,6 +123,7 @@ describe ('Parameter types', () => { const Maybe = $.UnaryType ('my-package/Maybe') ('http://example.com/my-package#Maybe') + ([]) (S.K (true)) (S.K ([])); @@ -143,25 +131,33 @@ describe ('Parameter types', () => { Maybe ($.Unknown), ]); const {types} = resolve ($) ([]) (env) ('foo :: Maybe String -> String'); - assertTypePairs (S.zip (types) ([Maybe ($.String), $.String])); + assertSameTypes (types) ([Maybe ($.String), $.String]); }); it ('should resolve eithers', () => { + const Either = $.BinaryType + ('my-package/Either') + ('http://example.com/my-package#Either') + ([]) + (x => x != null && x['@@type'] === 'my-package/Either') + (either => (either.isLeft ? [either.value] : [])) + (either => (either.isRight ? [either.value] : [])); + const env = $.env.concat ([ - S.EitherType ($.Unknown) ($.Unknown), + Either ($.Unknown) ($.Unknown), ]); const {types} = resolve ($) ([]) (env) ('foo :: Either String Number -> String'); - assertTypePairs (S.zip (types) ([S.EitherType ($.String) ($.Number), $.String])); + assertSameTypes (types) ([Either ($.String) ($.Number), $.String]); }); it ('should resolve thunks', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: () -> Number'); - assertTypePairs (S.zip (types) ([$.Number])); + assertSameTypes (types) ([$.Number]); }); it ('should resolve records', () => { const {types} = resolve ($) ([]) ($.env) ('foo :: { value :: Number } -> Number'); - assertTypePairs (S.zip (types) ([$.RecordType ({value: $.Number}), $.Number])); + assertSameTypes (types) ([$.RecordType ({value: $.Number}), $.Number]); }); it ('should resolve constraints', () => { @@ -170,6 +166,6 @@ describe ('Parameter types', () => { const f = $.UnaryTypeVariable ('f'); const tcs = [Z.Functor]; const {types} = resolve ($) (tcs) ($.env) ('foo :: Functor f => (a -> b) -> f a -> f b'); - assertTypePairs (S.zip (types) ([$.Function ([a, b]), f (a), f (b)])); + assertSameTypes (types) ([$.Function ([a, b]), f (a), f (b)]); }); }); diff --git a/yarn.lock b/yarn.lock index 88faab3..617731f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2944,39 +2944,39 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sanctuary-def@0.18.1, sanctuary-def@^0.18.1: - version "0.18.1" - resolved "https://registry.yarnpkg.com/sanctuary-def/-/sanctuary-def-0.18.1.tgz#580af82a3fbbd651e8dddc0ab34b11727ef63b5f" - integrity sha512-Ltu/gU5ZskRln8NI6YJru5JbpkcMe4XqFx5zJMZysTKPmOVkETys5eVvZmclNLzPNrOIPvqBGJtD/D2q9yvP/A== +sanctuary-def@0.20.1, sanctuary-def@^0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/sanctuary-def/-/sanctuary-def-0.20.1.tgz#172f70a694a0ae6d3944c95cda6a18744c4eeac7" + integrity sha512-WdOg5uDpqvplADyUb7pyDMNaT73TUzsE7VdKnZsEz6CwsNh46NSQAWZXM0i6IiqItnDtILkL5RGd4SGAvmjxLw== dependencies: - sanctuary-either "1.0.x" + sanctuary-either "1.2.0" sanctuary-show "1.0.x" - sanctuary-type-classes "9.0.x" + sanctuary-type-classes "11.0.x" sanctuary-type-identifiers "2.0.x" -sanctuary-either@1.0.0, sanctuary-either@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sanctuary-either/-/sanctuary-either-1.0.0.tgz#b6041e54c639700048be757ba4d6c026c2c2f67c" - integrity sha512-j4WAlwILU83wawXJQCSh5kVK27gxOykMuCfUfUOba/qUcFE+FxwHkt7lnHVYDjt7jG9SENe8bTQzPH/Zmhy3Ag== +sanctuary-either@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/sanctuary-either/-/sanctuary-either-1.2.0.tgz#3126196a2067ea4a9b1de6b6c4c045504059a44b" + integrity sha512-CFUK0OOGAe+t+Ct4yVLfkJPABIkplCvIgCOFIJZ+lIMNAeJrSaVacrZVqRErt4YKzDs42ZXecAEpoDL8rRAfsQ== dependencies: sanctuary-show "1.0.x" - sanctuary-type-classes "9.0.0" + sanctuary-type-classes "11.0.0" -sanctuary-maybe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sanctuary-maybe/-/sanctuary-maybe-1.0.0.tgz#03cd226d933ec89270e4495a965733390e843afc" - integrity sha512-4TUjIxznxTZ1dh8Zw4PRhaVkzY8KIZ4GGsOXBytOSV83MRRGkuz7wJHj3bfh2i9lOekbjf0Oal6v7IF6uDiYvg== +sanctuary-maybe@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/sanctuary-maybe/-/sanctuary-maybe-1.2.0.tgz#e994825d62f6d5a3c60771e859261b08c517acc5" + integrity sha512-SH4dkyrruJe84/q8YMjc6kWyGbqPH6clM6yfJ/iosQZm+bGK2XPgcPs1yDN0U0zm1JzJ563zdwn64W+aMw5CDw== dependencies: sanctuary-show "1.0.x" - sanctuary-type-classes "9.0.0" + sanctuary-type-classes "11.0.0" -sanctuary-pair@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sanctuary-pair/-/sanctuary-pair-1.0.0.tgz#eaf8121f0ba3064e5e0b09bb624bc3885209886a" - integrity sha512-fqXCO6boMLW7ZHrjc573u5maNdytIrNxeaotBBGrvbEVqiNeA6VH4eGARMLTCRdgOtW94aF5EUkBZCzvXLSujQ== +sanctuary-pair@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/sanctuary-pair/-/sanctuary-pair-1.2.0.tgz#2538dbdac011594fd601ca1112e83cb5083bc865" + integrity sha512-bPu+uFxFE2RP3hLlC6SRMsm4A2aEwHkDwHWuvGzHxYaclGnHCrHy0ykRTuR0Pgqy/ZlWl6zy+8Tek3jME3du6A== dependencies: sanctuary-show "1.0.x" - sanctuary-type-classes "9.0.0" + sanctuary-type-classes "11.0.0" sanctuary-show@1.0.0, sanctuary-show@1.0.x, sanctuary-show@^1.0.0: version "1.0.0" @@ -2988,7 +2988,14 @@ sanctuary-style@^2.0.0: resolved "https://registry.yarnpkg.com/sanctuary-style/-/sanctuary-style-2.0.0.tgz#83d023a340641bcc1d27acee013c098b12075586" integrity sha512-5g3UnBDY3419ipokMa/PXY9DM7XVU7sUMq3RMHRKnbqS9KYKWYvysljb8/rHi+bWut5n1omWEQJEyKUHY+482w== -sanctuary-type-classes@9.0.0, sanctuary-type-classes@9.0.x, sanctuary-type-classes@^9.0.0: +sanctuary-type-classes@11.0.0, sanctuary-type-classes@11.0.x, sanctuary-type-classes@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/sanctuary-type-classes/-/sanctuary-type-classes-11.0.0.tgz#f7f752a846aad057d894183a20169bc593ddb039" + integrity sha512-J9vfS19C9TSd0pIxz7dza0krxUGoo7LYdwQzkmO7zEsbzmPEwbB3HByLgN/zI+QYd0m08IdohAzYJSAd89Fdqg== + dependencies: + sanctuary-type-identifiers "2.0.1" + +sanctuary-type-classes@9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/sanctuary-type-classes/-/sanctuary-type-classes-9.0.0.tgz#b44741ca67fa650cbd314e1ad318d730ce1309a4" integrity sha512-rFW27f3D622kxKravpGU9OjWn66fnDjDjGPvoYo4hEoBg2ocypvp0R9cs0YovKL3jTO+PTceUBh5tYZ+l9ay3g== @@ -3005,17 +3012,17 @@ sanctuary-type-identifiers@2.0.1, sanctuary-type-identifiers@2.0.x: resolved "https://registry.yarnpkg.com/sanctuary-type-identifiers/-/sanctuary-type-identifiers-2.0.1.tgz#fc524cf6dd92cebfcbb0dd9509eff193159a20ed" integrity sha1-/FJM9t2Szr/LsN2VCe/xkxWaIO0= -sanctuary@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/sanctuary/-/sanctuary-0.15.0.tgz#a4b9bf7a43bad928dce3e7aa590fbf30681b9ebd" - integrity sha512-cyrFHazodEFlv6qVX/+qujO+jly2MXRMyNXR61jaqJG42JlCJnKpgQGvebYINaiRUbZ+P5Dr2Ai3Tg+vzNYCUw== +sanctuary@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sanctuary/-/sanctuary-2.0.1.tgz#cf19548bb8df2f52c9367faf8f7a7a4cf52af0ee" + integrity sha512-CQWjFRzSYrq8g16RCdfV4v1iJwyRRw3dhLizA/rKkKSu1L+5tTlBjQuZl25mKSd4S5oLdVTIJ1RlVktvns9R9g== dependencies: - sanctuary-def "0.18.1" - sanctuary-either "1.0.0" - sanctuary-maybe "1.0.0" - sanctuary-pair "1.0.0" + sanctuary-def "0.20.1" + sanctuary-either "1.2.0" + sanctuary-maybe "1.2.0" + sanctuary-pair "1.2.0" sanctuary-show "1.0.0" - sanctuary-type-classes "9.0.0" + sanctuary-type-classes "11.0.0" sanctuary-type-identifiers "2.0.1" sax@^1.2.4: