Skip to content

Commit

Permalink
classify: change S.is to take a sanctuary-def Type value
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchambers committed Mar 24, 2018
1 parent 743c4a5 commit 2970065
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 98 deletions.
51 changes: 21 additions & 30 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,32 +444,22 @@
return r;
});

//# is :: TypeRep a -> Any -> Boolean
//# is :: Type -> Any -> Boolean
//.
//. Takes a [type representative](#type-representatives) and a value of any
//. type and returns `true` [iff][] the given value is of the specified type.
//. Subtyping is not respected.
//. Returns `true` [iff][] the given value is a member of the specified type.
//. See [`$.test`][] for details.
//.
//. ```javascript
//. > S.is(Number, 42)
//. > S.is($.Array($.Integer), [1, 2, 3])
//. true
//.
//. > S.is(Object, 42)
//. false
//.
//. > S.is(String, 42)
//. > S.is($.Array($.Integer), [1, 2, 3.14])
//. false
//. ```
function is(typeRep, x) {
var xType = type(x);
if ($.String._test(typeRep['@@type'])) {
return xType === typeRep['@@type'];
} else {
var match = /function (\w*)/.exec(typeRep);
return match != null && match[1] === xType;
}
function is(type, x) {
return $.test(env, type, x);
}
S.is = def('is', {}, [TypeRep(a), $.Any, $.Boolean], is);
S.is = def('is', {}, [$.Type, $.Any, $.Boolean], is);

//. ### Showable

Expand Down Expand Up @@ -3641,19 +3631,19 @@
//. See also [`gets`](#gets) and [`prop`](#prop).
//.
//. ```javascript
//. > S.get(S.is(Number), 'x', {x: 1, y: 2})
//. > S.get(S.is($.Number), 'x', {x: 1, y: 2})
//. Just(1)
//.
//. > S.get(S.is(Number), 'x', {x: '1', y: '2'})
//. > S.get(S.is($.Number), 'x', {x: '1', y: '2'})
//. Nothing
//.
//. > S.get(S.is(Number), 'x', {})
//. > S.get(S.is($.Number), 'x', {})
//. Nothing
//.
//. > S.get($.test([], $.Array($.Number)), 'x', {x: [1, 2, 3]})
//. > S.get(S.is($.Array($.Number)), 'x', {x: [1, 2, 3]})
//. Just([1, 2, 3])
//.
//. > S.get($.test([], $.Array($.Number)), 'x', {x: [1, 2, 3, null]})
//. > S.get(S.is($.Array($.Number)), 'x', {x: [1, 2, 3, null]})
//. Nothing
//. ```
function get(pred, key, x) {
Expand All @@ -3675,13 +3665,13 @@
//. See also [`get`](#get).
//.
//. ```javascript
//. > S.gets(S.is(Number), ['a', 'b', 'c'], {a: {b: {c: 42}}})
//. > S.gets(S.is($.Number), ['a', 'b', 'c'], {a: {b: {c: 42}}})
//. Just(42)
//.
//. > S.gets(S.is(Number), ['a', 'b', 'c'], {a: {b: {c: '42'}}})
//. > S.gets(S.is($.Number), ['a', 'b', 'c'], {a: {b: {c: '42'}}})
//. Nothing
//.
//. > S.gets(S.is(Number), ['a', 'b', 'c'], {})
//. > S.gets(S.is($.Number), ['a', 'b', 'c'], {})
//. Nothing
//. ```
function gets(pred, keys, x) {
Expand Down Expand Up @@ -4173,16 +4163,16 @@
//. result satisfies the predicate; Nothing otherwise.
//.
//. ```javascript
//. > S.parseJson($.test([], $.Array($.Integer)), '[')
//. > S.parseJson(S.is($.Array($.Integer)), '[')
//. Nothing
//.
//. > S.parseJson($.test([], $.Array($.Integer)), '["1","2","3"]')
//. > S.parseJson(S.is($.Array($.Integer)), '["1","2","3"]')
//. Nothing
//.
//. > S.parseJson($.test([], $.Array($.Integer)), '[0,1.5,3,4.5]')
//. > S.parseJson(S.is($.Array($.Integer)), '[0,1.5,3,4.5]')
//. Nothing
//.
//. > S.parseJson($.test([], $.Array($.Integer)), '[1,2,3]')
//. > S.parseJson(S.is($.Array($.Integer)), '[1,2,3]')
//. Just([1, 2, 3])
//. ```
function parseJson(pred, s) {
Expand Down Expand Up @@ -4573,6 +4563,7 @@
//. [Semigroupoid]: v:fantasyland/fantasy-land#semigroupoid
//. [Traversable]: v:fantasyland/fantasy-land#traversable
//. [UnaryType]: v:sanctuary-js/sanctuary-def#UnaryType
//. [`$.test`]: v:sanctuary-js/sanctuary-def#test
//. [`Z.alt`]: v:sanctuary-js/sanctuary-type-classes#alt
//. [`Z.ap`]: v:sanctuary-js/sanctuary-type-classes#ap
//. [`Z.apFirst`]: v:sanctuary-js/sanctuary-type-classes#apFirst
Expand Down
18 changes: 8 additions & 10 deletions test/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,17 @@ test('get', function() {
eq(S.get.length, 3);
eq(S.get.toString(), 'get :: (Any -> Boolean) -> String -> a -> Maybe b');

eq(S.get(S.is(Number), 'x', {x: 0, y: 42}), S.Just(0));
eq(S.get(S.is(Number), 'y', {x: 0, y: 42}), S.Just(42));
eq(S.get(S.is(Number), 'z', {x: 0, y: 42}), S.Nothing);
eq(S.get(S.is(String), 'z', {x: 0, y: 42}), S.Nothing);
eq(S.get(S.is(String), 'x', {x: 0, y: 42}), S.Nothing);

eq(S.get(S.is(RegExp), 'x', {x: vm.runInNewContext('/.*/')}), S.Just(/.*/));
eq(S.get(S.is(vm.runInNewContext('RegExp')), 'x', {x: /.*/}), S.Just(/.*/));
eq(S.get(S.is($.Number), 'x', {x: 0, y: 42}), S.Just(0));
eq(S.get(S.is($.Number), 'y', {x: 0, y: 42}), S.Just(42));
eq(S.get(S.is($.Number), 'z', {x: 0, y: 42}), S.Nothing);
eq(S.get(S.is($.String), 'z', {x: 0, y: 42}), S.Nothing);
eq(S.get(S.is($.String), 'x', {x: 0, y: 42}), S.Nothing);
eq(S.get(S.is($.RegExp), 'x', {x: vm.runInNewContext('/.*/')}), S.Just(/.*/));

eq(S.get(S.K(true), 'valueOf', null), S.Nothing);
eq(S.get(S.K(true), 'valueOf', undefined), S.Nothing);

eq(S.get($.test([], $.Array($.Number)), 'x', {x: [1, 2]}), S.Just([1, 2]));
eq(S.get($.test([], $.Array($.Number)), 'x', {x: [1, 2, null]}), S.Nothing);
eq(S.get(S.is($.Array($.Number)), 'x', {x: [1, 2]}), S.Just([1, 2]));
eq(S.get(S.is($.Array($.Number)), 'x', {x: [1, 2, null]}), S.Nothing);

});
22 changes: 10 additions & 12 deletions test/gets.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,19 @@ test('gets', function() {
eq(S.gets.length, 3);
eq(S.gets.toString(), 'gets :: (Any -> Boolean) -> Array String -> a -> Maybe b');

eq(S.gets(S.is(Number), ['x'], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is(Number), ['y'], {x: {z: 0}, y: 42}), S.Just(42));
eq(S.gets(S.is(Number), ['z'], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is(Number), ['x', 'z'], {x: {z: 0}, y: 42}), S.Just(0));
eq(S.gets(S.is(Number), ['a', 'b', 'c'], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is(Number), [], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is(Object), [], {x: {z: 0}, y: 42}), S.Just({x: {z: 0}, y: 42}));

eq(S.gets(S.is(RegExp), ['x'], {x: vm.runInNewContext('/.*/')}), S.Just(/.*/));
eq(S.gets(S.is(vm.runInNewContext('RegExp')), ['x'], {x: /.*/}), S.Just(/.*/));
eq(S.gets(S.is($.Number), ['x'], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is($.Number), ['y'], {x: {z: 0}, y: 42}), S.Just(42));
eq(S.gets(S.is($.Number), ['z'], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is($.Number), ['x', 'z'], {x: {z: 0}, y: 42}), S.Just(0));
eq(S.gets(S.is($.Number), ['a', 'b', 'c'], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is($.Number), [], {x: {z: 0}, y: 42}), S.Nothing);
eq(S.gets(S.is($.Object), [], {x: {z: 0}, y: 42}), S.Just({x: {z: 0}, y: 42}));
eq(S.gets(S.is($.RegExp), ['x'], {x: vm.runInNewContext('/.*/')}), S.Just(/.*/));

eq(S.gets(S.K(true), ['valueOf'], null), S.Nothing);
eq(S.gets(S.K(true), ['valueOf'], undefined), S.Nothing);

eq(S.gets($.test([], $.Array($.Number)), ['x'], {x: [1, 2]}), S.Just([1, 2]));
eq(S.gets($.test([], $.Array($.Number)), ['x'], {x: [1, 2, null]}), S.Nothing);
eq(S.gets(S.is($.Array($.Number)), ['x'], {x: [1, 2]}), S.Just([1, 2]));
eq(S.gets(S.is($.Array($.Number)), ['x'], {x: [1, 2, null]}), S.Nothing);

});
80 changes: 40 additions & 40 deletions test/is.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
'use strict';

var vm = require('vm');
var $ = require('sanctuary-def');

var S = require('..');

var Sum = require('./internal/Sum');
var eq = require('./internal/eq');


test('is', function() {

eq(typeof S.is, 'function');
eq(S.is.length, 2);
eq(S.is.toString(), 'is :: TypeRep a -> Any -> Boolean');

eq(S.is(Array, []), true);
eq(S.is(Boolean, false), true);
eq(S.is(Date, new Date(0)), true);
eq(S.is(Function, function() {}), true);
eq(S.is(Number, 0), true);
eq(S.is(Object, {}), true);
eq(S.is(RegExp, /(?:)/), true);
eq(S.is(String, ''), true);
eq(S.is(Boolean, new Boolean(false)), true);
eq(S.is(Number, new Number(0)), true);
eq(S.is(String, new String('')), true);
eq(S.is(Array, null), false);
eq(S.is(Array, undefined), false);
eq(S.is(Array, {}), false);

eq(S.is(S.Maybe, S.Nothing), true);
eq(S.is(S.Maybe, S.Just(9)), true);
eq(S.is(S.Maybe, S.Left(9)), false);
eq(S.is(S.Maybe, S.Right(9)), false);

eq(S.is(S.Either, S.Nothing), false);
eq(S.is(S.Either, S.Just(9)), false);
eq(S.is(S.Either, S.Left(9)), true);
eq(S.is(S.Either, S.Right(9)), true);

function FooBar() {}
FooBar['@@type'] = 'foobar/FooBar';
function Foo() {}
Foo.prototype = new FooBar();
function Bar() {}
Bar.prototype = new FooBar();

eq(S.is(FooBar, new Foo()), true);
eq(S.is(FooBar, new Bar()), true);

eq(S.is(Array, vm.runInNewContext('[1, 2, 3]')), true);
eq(S.is(vm.runInNewContext('Array'), [1, 2, 3]), true);
eq(S.is.toString(), 'is :: Type -> Any -> Boolean');

eq(S.is($.Boolean, true), true);
eq(S.is($.Boolean, false), true);
eq(S.is($.Boolean, new Boolean(true)), false);
eq(S.is($.Boolean, new Boolean(false)), false);

eq(S.is($.Array($.Integer), null), false);
eq(S.is($.Array($.Integer), undefined), false);
eq(S.is($.Array($.Integer), ['1', '2', '3']), false);
eq(S.is($.Array($.Integer), [1, 2, 3.14]), false);
eq(S.is($.Array($.Integer), [1, 2, 3]), true);
eq(S.is($.Array($.Integer), []), true);

eq(S.is(S.MaybeType($.Integer), S.Nothing), true);
eq(S.is(S.MaybeType($.Integer), S.Just(0)), true);
eq(S.is(S.MaybeType($.Integer), S.Left(0)), false);
eq(S.is(S.MaybeType($.Integer), S.Right(0)), false);

eq(S.is(S.EitherType($.String, $.Integer), S.Nothing), false);
eq(S.is(S.EitherType($.String, $.Integer), S.Just(0)), false);
eq(S.is(S.EitherType($.String, $.Integer), S.Left(0)), false);
eq(S.is(S.EitherType($.String, $.Integer), S.Right('')), false);
eq(S.is(S.EitherType($.String, $.Integer), S.Left('')), true);
eq(S.is(S.EitherType($.String, $.Integer), S.Right(0)), true);

var a = $.TypeVariable('a');

eq(S.is($.Array(a), []), true);
eq(S.is($.Array(a), [1, 2, 3]), true);
eq(S.is($.Array(a), ['foo', 'bar', 'baz']), true);
eq(S.is($.Array(a), ['foo', true, 42]), false);
eq(S.is($.Array(a), [Sum(1), Sum(2), Sum(3)]), false);

eq(S.create({checkTypes: true, env: []}).is($.Array(a), []), true);
eq(S.create({checkTypes: true, env: []}).is($.Array(a), [1, 2, 3]), false);
eq(S.create({checkTypes: true, env: [$.Number]}).is($.Array(a), [1, 2, 3]), true);
eq(S.create({checkTypes: true, env: [Sum.Type]}).is($.Array(a), [Sum(1), Sum(2), Sum(3)]), true);

});
11 changes: 5 additions & 6 deletions test/parseJson.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ test('parseJson', function() {
eq(S.parseJson.length, 2);
eq(S.parseJson.toString(), 'parseJson :: (Any -> Boolean) -> String -> Maybe a');

eq(S.parseJson(S.is(Object), '[Invalid JSON]'), S.Nothing);
eq(S.parseJson(S.is(Array), '{"foo":"bar"}'), S.Nothing);
eq(S.parseJson(S.is(Array), '["foo","bar"]'), S.Just(['foo', 'bar']));

eq(S.parseJson($.test([], $.Array($.Number)), '[1,2]'), S.Just([1, 2]));
eq(S.parseJson($.test([], $.Array($.Number)), '[1,2,null]'), S.Nothing);
eq(S.parseJson(S.is($.Any), '[Invalid JSON]'), S.Nothing);
eq(S.parseJson(S.is($.Array($.Any)), '{"foo":"bar"}'), S.Nothing);
eq(S.parseJson(S.is($.Array($.Any)), '["foo","bar"]'), S.Just(['foo', 'bar']));
eq(S.parseJson(S.is($.Array($.Number)), '[1,2]'), S.Just([1, 2]));
eq(S.parseJson(S.is($.Array($.Number)), '[1,2,null]'), S.Nothing);

});

0 comments on commit 2970065

Please sign in to comment.