diff --git a/index.js b/index.js index dd53ec01..3a604fe9 100644 --- a/index.js +++ b/index.js @@ -3165,6 +3165,102 @@ : Just(result.total / result.count); }); + //# lt :: Ord a => a -> a -> Boolean + //. + //. Returns `true` if its first argument is smaller than its second + //. argument; `false` otherwise. + //. + //. Strings are compared lexicographically. Specifically, the Unicode + //. code point value of each character in the first string is compared + //. to the value of the corresponding character in the second string. + //. + //. See also [`lte`](#lte), [`gt`](#gt), and [`gte`](#gte). + //. + //. ```javascript + //. > S.lt(10, 2) + //. false + //. + //. > S.lt('10', '2') + //. true + //. ``` + S.lt = + def('lt', + {a: [Ord]}, + [a, a, $.Boolean], + function(x, y) { return x < y; }); + + //# lte :: Ord a => a -> a -> Boolean + //. + //. Returns `true` if its first argument is smaller than or equal to + //. its second argument; `false` otherwise. + //. + //. Strings are compared lexicographically. Specifically, the Unicode + //. code point value of each character in the first string is compared + //. to the value of the corresponding character in the second string. + //. + //. See also [`lt`](#lt), [`gt`](#gt), and [`gte`](#gte). + //. + //. ```javascript + //. > S.lte(10, 2) + //. false + //. + //. > S.lte('10', '2') + //. true + //. ``` + S.lte = + def('lte', + {a: [Ord]}, + [a, a, $.Boolean], + function(x, y) { return x <= y; }); + + //# gt :: Ord a => a -> a -> Boolean + //. + //. Returns `true` if its first argument is larger than its second + //. argument; `false` otherwise. + //. + //. Strings are compared lexicographically. Specifically, the Unicode + //. code point value of each character in the first string is compared + //. to the value of the corresponding character in the second string. + //. + //. See also [`gte`](#gte), [`lt`](#lt), and [`lte`](#lte). + //. + //. ```javascript + //. > S.gt(10, 2) + //. true + //. + //. > S.gt('10', '2') + //. false + //. ``` + S.gt = + def('gt', + {a: [Ord]}, + [a, a, $.Boolean], + function(x, y) { return x > y; }); + + //# gte :: Ord a => a -> a -> Boolean + //. + //. Returns `true` if its first argument is larger than or equal to + //. its second argument; `false` otherwise. + //. + //. Strings are compared lexicographically. Specifically, the Unicode + //. code point value of each character in the first string is compared + //. to the value of the corresponding character in the second string. + //. + //. See also [`gt`](#gt), [`lt`](#lt), and [`lte`](#lte). + //. + //. ```javascript + //. > S.gte(10, 2) + //. true + //. + //. > S.gte('10', '2') + //. false + //. ``` + S.gte = + def('gte', + {a: [Ord]}, + [a, a, $.Boolean], + function(x, y) { return x >= y; }); + //# min :: Ord a => a -> a -> a //. //. Returns the smaller of its two arguments. diff --git a/test/gt.js b/test/gt.js new file mode 100644 index 00000000..2053b4f3 --- /dev/null +++ b/test/gt.js @@ -0,0 +1,63 @@ +'use strict'; + +var throws = require('assert').throws; + +var S = require('..'); + +var eq = require('./internal/eq'); +var errorEq = require('./internal/errorEq'); + + +describe('gt', function() { + + it('is a binary function', function() { + eq(typeof S.gt, 'function'); + eq(S.gt.length, 2); + }); + + it('type checks its arguments', function() { + throws(function() { S.gt(null); }, + errorEq(TypeError, + 'Type-class constraint violation\n' + + '\n' + + 'gt :: Ord a => a -> a -> Boolean\n' + + ' ^^^^^ ^\n' + + ' 1\n' + + '\n' + + '1) null :: Null\n' + + '\n' + + '‘gt’ requires ‘a’ to satisfy the Ord type-class constraint; the value at position 1 does not.\n')); + + throws(function() { S.gt('abc', 123); }, + errorEq(TypeError, + 'Type-variable constraint violation\n' + + '\n' + + 'gt :: Ord a => a -> a -> Boolean\n' + + ' ^ ^\n' + + ' 1 2\n' + + '\n' + + '1) "abc" :: String\n' + + '\n' + + '2) 123 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' + + '\n' + + 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); + }); + + it('has > semantics', function() { + eq(S.gt(0, 0), false); + eq(S.gt(0, -0), false); + eq(S.gt(-0, 0), false); + eq(S.gt(-0, -0), false); + eq(S.gt(0, 1), false); + eq(S.gt(1, 0), true); + eq(S.gt(0, -1), true); + eq(S.gt(-1, 0), false); + eq(S.gt('a', 'a'), false); + eq(S.gt('a', 'z'), false); + eq(S.gt('z', 'a'), true); + eq(S.gt(new Date(0), new Date(0)), false); + eq(S.gt(new Date(0), new Date(1)), false); + eq(S.gt(new Date(1), new Date(0)), true); + }); + +}); diff --git a/test/gte.js b/test/gte.js new file mode 100644 index 00000000..5b07d3a5 --- /dev/null +++ b/test/gte.js @@ -0,0 +1,63 @@ +'use strict'; + +var throws = require('assert').throws; + +var S = require('..'); + +var eq = require('./internal/eq'); +var errorEq = require('./internal/errorEq'); + + +describe('gte', function() { + + it('is a binary function', function() { + eq(typeof S.gte, 'function'); + eq(S.gte.length, 2); + }); + + it('type checks its arguments', function() { + throws(function() { S.gte(null); }, + errorEq(TypeError, + 'Type-class constraint violation\n' + + '\n' + + 'gte :: Ord a => a -> a -> Boolean\n' + + ' ^^^^^ ^\n' + + ' 1\n' + + '\n' + + '1) null :: Null\n' + + '\n' + + '‘gte’ requires ‘a’ to satisfy the Ord type-class constraint; the value at position 1 does not.\n')); + + throws(function() { S.gte('abc', 123); }, + errorEq(TypeError, + 'Type-variable constraint violation\n' + + '\n' + + 'gte :: Ord a => a -> a -> Boolean\n' + + ' ^ ^\n' + + ' 1 2\n' + + '\n' + + '1) "abc" :: String\n' + + '\n' + + '2) 123 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' + + '\n' + + 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); + }); + + it('has >= semantics', function() { + eq(S.gte(0, 0), true); + eq(S.gte(0, -0), true); + eq(S.gte(-0, 0), true); + eq(S.gte(-0, -0), true); + eq(S.gte(0, 1), false); + eq(S.gte(1, 0), true); + eq(S.gte(0, -1), true); + eq(S.gte(-1, 0), false); + eq(S.gte('a', 'a'), true); + eq(S.gte('a', 'z'), false); + eq(S.gte('z', 'a'), true); + eq(S.gte(new Date(0), new Date(0)), true); + eq(S.gte(new Date(0), new Date(1)), false); + eq(S.gte(new Date(1), new Date(0)), true); + }); + +}); diff --git a/test/lt.js b/test/lt.js new file mode 100644 index 00000000..9c3955be --- /dev/null +++ b/test/lt.js @@ -0,0 +1,63 @@ +'use strict'; + +var throws = require('assert').throws; + +var S = require('..'); + +var eq = require('./internal/eq'); +var errorEq = require('./internal/errorEq'); + + +describe('lt', function() { + + it('is a binary function', function() { + eq(typeof S.lt, 'function'); + eq(S.lt.length, 2); + }); + + it('type checks its arguments', function() { + throws(function() { S.lt(null); }, + errorEq(TypeError, + 'Type-class constraint violation\n' + + '\n' + + 'lt :: Ord a => a -> a -> Boolean\n' + + ' ^^^^^ ^\n' + + ' 1\n' + + '\n' + + '1) null :: Null\n' + + '\n' + + '‘lt’ requires ‘a’ to satisfy the Ord type-class constraint; the value at position 1 does not.\n')); + + throws(function() { S.lt('abc', 123); }, + errorEq(TypeError, + 'Type-variable constraint violation\n' + + '\n' + + 'lt :: Ord a => a -> a -> Boolean\n' + + ' ^ ^\n' + + ' 1 2\n' + + '\n' + + '1) "abc" :: String\n' + + '\n' + + '2) 123 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' + + '\n' + + 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); + }); + + it('has < semantics', function() { + eq(S.lt(0, 0), false); + eq(S.lt(0, -0), false); + eq(S.lt(-0, 0), false); + eq(S.lt(-0, -0), false); + eq(S.lt(0, 1), true); + eq(S.lt(1, 0), false); + eq(S.lt(0, -1), false); + eq(S.lt(-1, 0), true); + eq(S.lt('a', 'a'), false); + eq(S.lt('a', 'z'), true); + eq(S.lt('z', 'a'), false); + eq(S.lt(new Date(0), new Date(0)), false); + eq(S.lt(new Date(0), new Date(1)), true); + eq(S.lt(new Date(1), new Date(0)), false); + }); + +}); diff --git a/test/lte.js b/test/lte.js new file mode 100644 index 00000000..0ec43430 --- /dev/null +++ b/test/lte.js @@ -0,0 +1,63 @@ +'use strict'; + +var throws = require('assert').throws; + +var S = require('..'); + +var eq = require('./internal/eq'); +var errorEq = require('./internal/errorEq'); + + +describe('lte', function() { + + it('is a binary function', function() { + eq(typeof S.lte, 'function'); + eq(S.lte.length, 2); + }); + + it('type checks its arguments', function() { + throws(function() { S.lte(null); }, + errorEq(TypeError, + 'Type-class constraint violation\n' + + '\n' + + 'lte :: Ord a => a -> a -> Boolean\n' + + ' ^^^^^ ^\n' + + ' 1\n' + + '\n' + + '1) null :: Null\n' + + '\n' + + '‘lte’ requires ‘a’ to satisfy the Ord type-class constraint; the value at position 1 does not.\n')); + + throws(function() { S.lte('abc', 123); }, + errorEq(TypeError, + 'Type-variable constraint violation\n' + + '\n' + + 'lte :: Ord a => a -> a -> Boolean\n' + + ' ^ ^\n' + + ' 1 2\n' + + '\n' + + '1) "abc" :: String\n' + + '\n' + + '2) 123 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' + + '\n' + + 'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n')); + }); + + it('has <= semantics', function() { + eq(S.lte(0, 0), true); + eq(S.lte(0, -0), true); + eq(S.lte(-0, 0), true); + eq(S.lte(-0, -0), true); + eq(S.lte(0, 1), true); + eq(S.lte(1, 0), false); + eq(S.lte(0, -1), false); + eq(S.lte(-1, 0), true); + eq(S.lte('a', 'a'), true); + eq(S.lte('a', 'z'), true); + eq(S.lte('z', 'a'), false); + eq(S.lte(new Date(0), new Date(0)), true); + eq(S.lte(new Date(0), new Date(1)), true); + eq(S.lte(new Date(1), new Date(0)), false); + }); + +});