diff --git a/index.js b/index.js index f9de4df9..112358a4 100644 --- a/index.js +++ b/index.js @@ -284,15 +284,6 @@ } ); - // Monoid :: TypeClass - var Monoid = $.TypeClass( - 'sanctuary/Monoid', - function(x) { - return R.contains(R.type(x), ['Array', 'Boolean', 'String']) || - hasMethod('empty')(x); - } - ); - // Ord :: TypeClass var Ord = $.TypeClass( 'sanctuary/Ord', @@ -1096,26 +1087,6 @@ [$Maybe(a), $.Function, b], Maybe$prototype$sequence); - //# Maybe#toBoolean :: Maybe a ~> () -> Boolean - //. - //. Returns `false` if `this` is Nothing; `true` if `this` is a Just. - //. - //. ```javascript - //. > S.Nothing.toBoolean() - //. false - //. - //. > S.Just(42).toBoolean() - //. true - //. ``` - function Maybe$prototype$toBoolean(self) { - return self.isJust; - } - Maybe.prototype.toBoolean = - method('Maybe#toBoolean', - {}, - [$Maybe(a), $.Boolean], - Maybe$prototype$toBoolean); - //# Maybe#toString :: Maybe a ~> () -> String //. //. Returns the string representation of the Maybe. @@ -1704,26 +1675,6 @@ [$Either(a, b), $.Function, c], Either$prototype$sequence); - //# Either#toBoolean :: Either a b ~> () -> Boolean - //. - //. Returns `false` if `this` is a Left; `true` if `this` is a Right. - //. - //. ```javascript - //. > S.Left(42).toBoolean() - //. false - //. - //. > S.Right(42).toBoolean() - //. true - //. ``` - function Either$prototype$toBoolean(self) { - return self.isRight; - } - Either.prototype.toBoolean = - method('Either#toBoolean', - {}, - [$Either(a, b), $.Boolean], - Either$prototype$toBoolean); - //# Either#toString :: Either a b ~> () -> String //. //. Returns the string representation of the Either. @@ -2033,108 +1984,62 @@ S.eitherToMaybe = def('eitherToMaybe', {}, [$Either(a, b), $Maybe(b)], eitherToMaybe); - //. ### Alternative - - // Alternative :: TypeClass - var Alternative = $.TypeClass( - 'Alternative', - function(x) { - return R.contains(R.type(x), ['Array', 'Boolean']) || - hasMethod('toBoolean')(x); - } - ); - - // toBoolean :: Alternative a => a -> Boolean - var toBoolean = function(x) { - switch (R.type(x)) { - case 'Array': return x.length > 0; - case 'Boolean': return x.valueOf(); - default: return x.toBoolean(); - } - }; - - // empty :: Monoid a => a -> a - var empty = function(x) { - switch (R.type(x)) { - case 'Array': return []; - case 'Boolean': return false; - default: return x.empty(); - } - }; + //. ### Logic - //# and :: Alternative a => a -> a -> a + //# and :: Boolean -> Boolean -> Boolean //. - //. Takes two values of the same type and returns the second value - //. if the first is "true"; the first value otherwise. An array is - //. considered "true" if its length is greater than zero. The Boolean - //. value `true` is also considered "true". Other types must provide - //. a `toBoolean` method. + //. Boolean "and". //. //. ```javascript - //. > S.and(S.Just(1), S.Just(2)) - //. Just(2) + //. > S.and(false, false) + //. false //. - //. > S.and(S.Nothing, S.Just(3)) - //. Nothing + //. > S.and(false, true) + //. false + //. + //. > S.and(true, false) + //. false + //. + //. > S.and(true, true) + //. true //. ``` function and(x, y) { - return toBoolean(x) ? y : x; + return x.valueOf() && y.valueOf(); } - S.and = def('and', {a: [Alternative]}, [a, a, a], and); + S.and = def('and', {}, [$.Boolean, $.Boolean, $.Boolean], and); - //# or :: Alternative a => a -> a -> a + //# or :: Boolean -> Boolean -> Boolean //. - //. Takes two values of the same type and returns the first value if it - //. is "true"; the second value otherwise. An array is considered "true" - //. if its length is greater than zero. The Boolean value `true` is also - //. considered "true". Other types must provide a `toBoolean` method. + //. Boolean "or". //. //. ```javascript - //. > S.or(S.Just(1), S.Just(2)) - //. Just(1) - //. - //. > S.or(S.Nothing, S.Just(3)) - //. Just(3) - //. ``` - function or(x, y) { - return toBoolean(x) ? x : y; - } - S.or = def('or', {a: [Alternative]}, [a, a, a], or); - - //# xor :: (Alternative a, Monoid a) => a -> a -> a + //. > S.or(false, false) + //. false //. - //. Takes two values of the same type and returns the "true" value - //. if one value is "true" and the other is "false"; otherwise it - //. returns the type's "false" value. An array is considered "true" - //. if its length is greater than zero. The Boolean value `true` is - //. also considered "true". Other types must provide `toBoolean` and - //. `empty` methods. + //. > S.or(false, true) + //. true //. - //. ```javascript - //. > S.xor(S.Nothing, S.Just(1)) - //. Just(1) + //. > S.or(true, false) + //. true //. - //. > S.xor(S.Just(2), S.Just(3)) - //. Nothing + //. > S.or(true, true) + //. true //. ``` - function xor(x, y) { - return toBoolean(x) === toBoolean(y) ? empty(x) : or(x, y); + function or(x, y) { + return x.valueOf() || y.valueOf(); } - S.xor = def('xor', {a: [Alternative, Monoid]}, [a, a, a], xor); - - //. ### Logic + S.or = def('or', {}, [$.Boolean, $.Boolean, $.Boolean], or); //# not :: Boolean -> Boolean //. - //. Takes a Boolean and returns the negation of that value - //. (`false` for `true`; `true` for `false`). + //. Boolean "not". //. //. ```javascript - //. > S.not(true) - //. false - //. //. > S.not(false) //. true + //. + //. > S.not(true) + //. false //. ``` function not(x) { return !x.valueOf(); diff --git a/test/Either/Left.js b/test/Either/Left.js index 4f2b77bf..15ab1cdd 100644 --- a/test/Either/Left.js +++ b/test/Either/Left.js @@ -187,11 +187,6 @@ describe('Left', function() { eq(S.Left('abc').sequence(S.Maybe.of), S.Just(S.Left('abc'))); }); - it('provides a "toBoolean" method', function() { - eq(S.Left('abc').toBoolean.length, 0); - eq(S.Left('abc').toBoolean(), false); - }); - it('provides a "toString" method', function() { eq(S.Left('abc').toString.length, 0); eq(S.Left('abc').toString(), 'Left("abc")'); diff --git a/test/Either/Right.js b/test/Either/Right.js index 2b397799..59f0140f 100644 --- a/test/Either/Right.js +++ b/test/Either/Right.js @@ -187,11 +187,6 @@ describe('Right', function() { eq(S.Right(S.Just(42)).sequence(S.Maybe.of), S.Just(S.Right(42))); }); - it('provides a "toBoolean" method', function() { - eq(S.Right(42).toBoolean.length, 0); - eq(S.Right(42).toBoolean(), true); - }); - it('provides a "toString" method', function() { eq(S.Right([1, 2, 3]).toString.length, 0); eq(S.Right([1, 2, 3]).toString(), 'Right([1, 2, 3])'); diff --git a/test/Maybe/Just.js b/test/Maybe/Just.js index 6ef20890..f1006d5a 100644 --- a/test/Maybe/Just.js +++ b/test/Maybe/Just.js @@ -215,11 +215,6 @@ describe('Just', function() { eq(S.Just(S.Right(42)).sequence(S.Either.of), S.Right(S.Just(42))); }); - it('provides a "toBoolean" method', function() { - eq(S.Just(42).toBoolean.length, 0); - eq(S.Just(42).toBoolean(), true); - }); - it('provides a "toString" method', function() { eq(S.Just([1, 2, 3]).toString.length, 0); eq(S.Just([1, 2, 3]).toString(), 'Just([1, 2, 3])'); diff --git a/test/Maybe/Nothing.js b/test/Maybe/Nothing.js index f71cea16..550fcec7 100644 --- a/test/Maybe/Nothing.js +++ b/test/Maybe/Nothing.js @@ -178,11 +178,6 @@ describe('Nothing', function() { eq(S.Nothing.sequence(S.Either.of), S.Right(S.Nothing)); }); - it('provides a "toBoolean" method', function() { - eq(S.Nothing.toBoolean.length, 0); - eq(S.Nothing.toBoolean(), false); - }); - it('provides a "toString" method', function() { eq(S.Nothing.toString.length, 0); eq(S.Nothing.toString(), 'Nothing'); diff --git a/test/and.js b/test/and.js index 87928926..b377988f 100644 --- a/test/and.js +++ b/test/and.js @@ -1,13 +1,8 @@ 'use strict'; -var throws = require('assert').throws; - -var R = require('ramda'); - var S = require('..'); var eq = require('./internal/eq'); -var errorEq = require('./internal/errorEq'); describe('and', function() { @@ -17,76 +12,15 @@ describe('and', function() { eq(S.and.length, 2); }); - it('can be applied to Booleans', function() { + it('has && semantics', function() { eq(S.and(false, false), false); eq(S.and(false, true), false); eq(S.and(true, false), false); eq(S.and(true, true), true); - }); - - it('can be applied to arrays', function() { - eq(S.and([], []), []); - eq(S.and([], [42]), []); - eq(S.and([42], []), []); - eq(S.and([42], [43]), [43]); - }); - - it('can be applied to maybes', function() { - eq(S.and(S.Nothing, S.Nothing), S.Nothing); - eq(S.and(S.Nothing, S.Just(42)), S.Nothing); - eq(S.and(S.Just(42), S.Nothing), S.Nothing); - eq(S.and(S.Just(42), S.Just(43)), S.Just(43)); - }); - - it('can be applied to eithers', function() { - eq(S.and(S.Left('foo'), S.Left('bar')), S.Left('foo')); - eq(S.and(S.Left('foo'), S.Right(42)), S.Left('foo')); - eq(S.and(S.Right(42), S.Left('foo')), S.Left('foo')); - eq(S.and(S.Right(42), S.Right(43)), S.Right(43)); - }); - - it('throws if applied to values of different types', function() { - throws(function() { S.and([], false); }, - errorEq(TypeError, - 'Type-variable constraint violation\n' + - '\n' + - 'and :: Alternative a => a -> a -> a\n' + - ' ^ ^\n' + - ' 1 2\n' + - '\n' + - '1) [] :: Array ???\n' + - '\n' + - '2) false :: Boolean\n' + - '\n' + - 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); - - throws(function() { S.and(R.__, false)([]); }, - errorEq(TypeError, - 'Type-variable constraint violation\n' + - '\n' + - 'and :: Alternative a => a -> a -> a\n' + - ' ^ ^\n' + - ' 1 2\n' + - '\n' + - '1) [] :: Array ???\n' + - '\n' + - '2) false :: Boolean\n' + - '\n' + - 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); - }); - - it('throws if applied to values without a "toBoolean" method', function() { - throws(function() { S.and(0, 1); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'and :: Alternative a => a -> a -> a\n' + - ' ^^^^^^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) 0 :: Number, FiniteNumber, Integer, ValidNumber\n' + - '\n' + - '‘and’ requires ‘a’ to satisfy the Alternative type-class constraint; the value at position 1 does not.\n')); + eq(S.and(new Boolean(false), new Boolean(false)), false); + eq(S.and(new Boolean(false), new Boolean(true)), false); + eq(S.and(new Boolean(true), new Boolean(false)), false); + eq(S.and(new Boolean(true), new Boolean(true)), true); }); }); diff --git a/test/or.js b/test/or.js index 111e827b..7177cad4 100644 --- a/test/or.js +++ b/test/or.js @@ -1,13 +1,8 @@ 'use strict'; -var throws = require('assert').throws; - -var R = require('ramda'); - var S = require('..'); var eq = require('./internal/eq'); -var errorEq = require('./internal/errorEq'); describe('or', function() { @@ -17,76 +12,15 @@ describe('or', function() { eq(S.or.length, 2); }); - it('can be applied to Booleans', function() { + it('has || semantics', function() { eq(S.or(false, false), false); eq(S.or(false, true), true); eq(S.or(true, false), true); eq(S.or(true, true), true); - }); - - it('can be applied to arrays', function() { - eq(S.or([], []), []); - eq(S.or([], [42]), [42]); - eq(S.or([42], []), [42]); - eq(S.or([42], [43]), [42]); - }); - - it('can be applied to maybes', function() { - eq(S.or(S.Nothing, S.Nothing), S.Nothing); - eq(S.or(S.Nothing, S.Just(42)), S.Just(42)); - eq(S.or(S.Just(42), S.Nothing), S.Just(42)); - eq(S.or(S.Just(42), S.Just(43)), S.Just(42)); - }); - - it('can be applied to eithers', function() { - eq(S.or(S.Left('foo'), S.Left('bar')), S.Left('bar')); - eq(S.or(S.Left('foo'), S.Right(42)), S.Right(42)); - eq(S.or(S.Right(42), S.Left('foo')), S.Right(42)); - eq(S.or(S.Right(42), S.Right(43)), S.Right(42)); - }); - - it('throws if applied to values of different types', function() { - throws(function() { S.or([], false); }, - errorEq(TypeError, - 'Type-variable constraint violation\n' + - '\n' + - 'or :: Alternative a => a -> a -> a\n' + - ' ^ ^\n' + - ' 1 2\n' + - '\n' + - '1) [] :: Array ???\n' + - '\n' + - '2) false :: Boolean\n' + - '\n' + - 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); - - throws(function() { S.or(R.__, false)([]); }, - errorEq(TypeError, - 'Type-variable constraint violation\n' + - '\n' + - 'or :: Alternative a => a -> a -> a\n' + - ' ^ ^\n' + - ' 1 2\n' + - '\n' + - '1) [] :: Array ???\n' + - '\n' + - '2) false :: Boolean\n' + - '\n' + - 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); - }); - - it('throws if applied to values without a "toBoolean" method', function() { - throws(function() { S.or(0, 1); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'or :: Alternative a => a -> a -> a\n' + - ' ^^^^^^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) 0 :: Number, FiniteNumber, Integer, ValidNumber\n' + - '\n' + - '‘or’ requires ‘a’ to satisfy the Alternative type-class constraint; the value at position 1 does not.\n')); + eq(S.or(new Boolean(false), new Boolean(false)), false); + eq(S.or(new Boolean(false), new Boolean(true)), true); + eq(S.or(new Boolean(true), new Boolean(false)), true); + eq(S.or(new Boolean(true), new Boolean(true)), true); }); }); diff --git a/test/xor.js b/test/xor.js deleted file mode 100644 index b79b9d22..00000000 --- a/test/xor.js +++ /dev/null @@ -1,135 +0,0 @@ -'use strict'; - -var throws = require('assert').throws; - -var R = require('ramda'); - -var S = require('..'); - -var eq = require('./internal/eq'); -var errorEq = require('./internal/errorEq'); - - -describe('xor', function() { - - it('is a binary function', function() { - eq(typeof S.xor, 'function'); - eq(S.xor.length, 2); - }); - - it('can be applied to Booleans', function() { - eq(S.xor(false, false), false); - eq(S.xor(false, true), true); - eq(S.xor(true, false), true); - eq(S.xor(true, true), false); - }); - - it('can be applied to arrays', function() { - eq(S.xor([], []), []); - eq(S.xor([], [42]), [42]); - eq(S.xor([42], []), [42]); - eq(S.xor([42], [43]), []); - }); - - it('can be applied to maybes', function() { - eq(S.xor(S.Nothing, S.Nothing), S.Nothing); - eq(S.xor(S.Nothing, S.Just(42)), S.Just(42)); - eq(S.xor(S.Just(42), S.Nothing), S.Just(42)); - eq(S.xor(S.Just(42), S.Just(43)), S.Nothing); - }); - - it('cannot be applied to eithers', function() { - throws(function() { S.xor(S.Left('foo'), S.Left('bar')); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) Left("foo") :: Either String ???\n' + - '\n' + - '‘xor’ requires ‘a’ to satisfy the Monoid type-class constraint; the value at position 1 does not.\n')); - - throws(function() { S.xor(S.Left('foo'), S.Right(42)); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) Left("foo") :: Either String ???\n' + - '\n' + - '‘xor’ requires ‘a’ to satisfy the Monoid type-class constraint; the value at position 1 does not.\n')); - - throws(function() { S.xor(S.Right(42), S.Left('foo')); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) Right(42) :: Either ??? Number, Either ??? FiniteNumber, Either ??? NonZeroFiniteNumber, Either ??? Integer, Either ??? ValidNumber\n' + - '\n' + - '‘xor’ requires ‘a’ to satisfy the Monoid type-class constraint; the value at position 1 does not.\n')); - - throws(function() { S.xor(S.Right(42), S.Right(43)); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) Right(42) :: Either ??? Number, Either ??? FiniteNumber, Either ??? NonZeroFiniteNumber, Either ??? Integer, Either ??? ValidNumber\n' + - '\n' + - '‘xor’ requires ‘a’ to satisfy the Monoid type-class constraint; the value at position 1 does not.\n')); - }); - - it('throws if applied to values of different types', function() { - throws(function() { S.xor([], false); }, - errorEq(TypeError, - 'Type-variable constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^ ^\n' + - ' 1 2\n' + - '\n' + - '1) [] :: Array ???\n' + - '\n' + - '2) false :: Boolean\n' + - '\n' + - 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); - - throws(function() { S.xor(R.__, false)([]); }, - errorEq(TypeError, - 'Type-variable constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^ ^\n' + - ' 1 2\n' + - '\n' + - '1) [] :: Array ???\n' + - '\n' + - '2) false :: Boolean\n' + - '\n' + - 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); - }); - - it('throws if applied to values without a "toBoolean" method', function() { - throws(function() { S.xor(0, 1); }, - errorEq(TypeError, - 'Type-class constraint violation\n' + - '\n' + - 'xor :: (Alternative a, Monoid a) => a -> a -> a\n' + - ' ^^^^^^^^^^^^^ ^\n' + - ' 1\n' + - '\n' + - '1) 0 :: Number, FiniteNumber, Integer, ValidNumber\n' + - '\n' + - '‘xor’ requires ‘a’ to satisfy the Alternative type-class constraint; the value at position 1 does not.\n')); - }); - -});