diff --git a/lib/validation.js b/lib/validation.js index 7cea38e..654c89a 100644 --- a/lib/validation.js +++ b/lib/validation.js @@ -17,12 +17,12 @@ */ function valid(value) { return { - valid : true - , value : value - , map : function(f) { return valid(f(value)); } - , flatMap : function(f) { return f(value); } - , ap : function(a) { return a.map(value); } - , toString : function() { return 'valid(' + value.toString() + ')'; } + valid : true, + value : value, + map : function(f) { return valid(f(value)); }, + flatMap : function(f) { return f(value); }, + ap : function(a) { return a.map(value); }, + toString : function() { return 'valid(' + value.toString() + ')'; } }; } @@ -34,8 +34,8 @@ function valid(value) { * * * `valid` - returns false * * `errors` - returns the array of errors - * * `map(f) - returns a this validation - * * `flatMap(f) - returns this validation + * * `map(f)` - returns a this validation + * * `flatMap(f)` - returns this validation * * `ap(a)` - if `a` is valid, return this validation, otherwise returns a new (invalid) validation containing the concatenation of this validation's errors with `a`'s errors * * `toString()` * @@ -44,15 +44,15 @@ function valid(value) { */ function invalid(errors) { return { - valid : false - , errors : errors - , map : function(f) { return this; } - , flatMap : function(f) { return this; } - , ap : function(a) { - if (a.valid) { return this; } - else { return invalid(this.errors.concat(a.errors)); } - } - , toString : function() { return 'invalid(' + errors.toString() + ')'; } + valid : false, + errors : errors, + map : function() { return this; }, + flatMap : function() { return this; }, + ap : function(a) { + if (a.valid) { return this; } + else { return invalid(this.errors.concat(a.errors)); } + }, + toString : function() { return 'invalid(' + errors.toString() + ')'; } }; } diff --git a/test/list_test.js b/test/list_test.js index 638c870..c507cdf 100644 --- a/test/list_test.js +++ b/test/list_test.js @@ -29,7 +29,7 @@ exports['list'] = { test.done(); }, - 'length': function(test) { + 'length': function(test) { test.expect(3); test.equal(4, list(0, list(1, list())).concat(list(2, list(3, list()))).length); @@ -84,6 +84,49 @@ exports['list'] = { test.equal(l5.toString(), 'cons(d, cons(c, cons(b, cons(a, nil))))'); test.equal(l6.toString(), 'cons(d, cons(c, cons(b, cons(a, nil))))'); + test.done(); + }, + 'map': function(test) { + test.expect(3); + + function square(x) { + return x * x; + } + + var l1 = list(); + var l2 = list(2); + var l3 = list(3, l2); + + var l1s = l1.map(square); + var l2s = l2.map(square); + var l3s = l3.map(square); + + test.equal(l1s.toString(), 'nil'); + test.equal(l2s.toString(), 'cons(4, nil)'); + test.equal(l3s.toString(), 'cons(9, cons(4, nil))'); + + test.done(); + }, + 'flatMap': function(test) { + test.expect(3); + + function squareAndRepeat(x) { + var s = x * x; + return list(s, list(s)); + } + + var l1 = list(); + var l2 = list(2); + var l3 = list(3, l2); + + var l1s = l1.flatMap(squareAndRepeat); + var l2s = l2.flatMap(squareAndRepeat); + var l3s = l3.flatMap(squareAndRepeat); + + test.equal(l1s.toString(), 'nil'); + test.equal(l2s.toString(), 'cons(4, cons(4, nil))'); + test.equal(l3s.toString(), 'cons(9, cons(9, cons(4, cons(4, nil))))'); + test.done(); }, }; diff --git a/test/option_test.js b/test/option_test.js index 9d7da24..97baeb5 100644 --- a/test/option_test.js +++ b/test/option_test.js @@ -33,4 +33,17 @@ exports['option'] = { test.equal(teep.option(41).map(inc).toString(), 'some(42)', 'should be 42.'); test.done(); }, + 'flatMap': function(test) { + function incLift(x) { return teep.option(1 + x); } + test.expect(2); + test.equal(teep.option().flatMap(incLift).toString(), 'none()', 'should be empty.'); + test.equal(teep.option(41).flatMap(incLift).toString(), 'some(42)', 'should be 42.'); + test.done(); + }, + 'ap': function(test) { + test.expect(2); + test.equal(teep.option().ap(teep.option(41)).toString(), 'none()', 'should be empty.'); + test.equal(teep.option(inc).ap(teep.option(41)).toString(), 'some(42)', 'should be 42.'); + test.done(); + }, }; diff --git a/test/validation_test.js b/test/validation_test.js index 68568fe..0ea25cc 100644 --- a/test/validation_test.js +++ b/test/validation_test.js @@ -11,4 +11,17 @@ exports['validation'] = { test.equal(teep.invalid(['wat']).map(inc).toString(), 'invalid(wat)', 'should be invalid(wat).'); test.done(); }, + 'flatMap': function(test) { + function incLift(x) { return teep.valid(1 + x); } + test.expect(2); + test.equal(teep.valid(41).flatMap(incLift).toString(), 'valid(42)', 'should be 42.'); + test.equal(teep.invalid(['wat']).flatMap(incLift).toString(), 'invalid(wat)', 'should be invalid(wat).'); + test.done(); + }, + 'ap': function(test) { + test.expect(2); + test.equal(teep.valid(inc).ap(teep.valid(41)).toString(), 'valid(42)', 'should be 42.'); + test.equal(teep.invalid(['wat']).ap(teep.valid(41)).toString(), 'invalid(wat)', 'should be invalid(wat).'); + test.done(); + }, };