Skip to content

Commit

Permalink
Merge pull request #204 from sanctuary-js/dc-either
Browse files Browse the repository at this point in the history
either: implement Foldable
  • Loading branch information
davidchambers committed May 1, 2016
2 parents 4f7c343 + 1f0c2a1 commit b149c57
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
30 changes: 27 additions & 3 deletions index.js
Expand Up @@ -973,7 +973,7 @@
[b, $Maybe(b)],
Maybe.of);

//# Maybe#reduce :: Maybe a ~> (b -> a -> b) -> b -> b
//# Maybe#reduce :: Maybe a ~> ((b, a) -> b) -> b -> b
//.
//. Takes a function and an initial value of any type, and returns:
//.
Expand Down Expand Up @@ -1357,8 +1357,8 @@
//. `Either a b` is either a Left whose value is of type `a` or a Right whose
//. value is of type `b`.
//.
//. The Either type satisfies the [Semigroup][], [Monad][], and [Extend][]
//. specifications.
//. The Either type satisfies the [Semigroup][], [Monad][], [Foldable][], and
//. [Extend][] specifications.

//# EitherType :: Type -> Type -> Type
//.
Expand Down Expand Up @@ -1591,6 +1591,30 @@
[c, $Either(a, c)],
Either.of);

//# Either#reduce :: Either a b ~> ((c, b) -> c) -> c -> c
//.
//. Takes a function and an initial value of any type, and returns:
//.
//. - the initial value if `this` is a Left; otherwise
//.
//. - the result of applying the function to the initial value and this
//. Right's value.
//.
//. ```javascript
//. > S.Left('Cannot divide by zero').reduce((xs, x) => xs.concat([x]), [42])
//. [42]
//.
//. > S.Right(5).reduce((xs, x) => xs.concat([x]), [42])
//. [42, 5]
//. ```
Either.prototype.reduce =
method('Either#reduce',
{},
[$Either(a, b), $.Function, c, c],
function(either, f, x) {
return either.isRight ? f(x, either.value) : x;
});

//# Either#toBoolean :: Either a b ~> Boolean
//.
//. Returns `false` if `this` is a Left; `true` if `this` is a Right.
Expand Down
18 changes: 18 additions & 0 deletions test/Either/Left.js
Expand Up @@ -167,6 +167,24 @@ describe('Left', function() {
'The value at position 1 is not a member of ‘Function’.\n'));
});

it('provides a "reduce" method', function() {
eq(S.Left().reduce.length, 2);
eq(S.Left().reduce(function(xs, x) { return xs.concat([x]); }, [42]),
[42]);

throws(function() { S.Left().reduce(null, null); },
errorEq(TypeError,
'Invalid value\n' +
'\n' +
'Either#reduce :: Either a b -> Function -> c -> c\n' +
' ^^^^^^^^\n' +
' 1\n' +
'\n' +
'1) null :: Null\n' +
'\n' +
'The value at position 1 is not a member of ‘Function’.\n'));
});

it('provides a "toBoolean" method', function() {
eq(S.Left('abc').toBoolean.length, 0);
eq(S.Left('abc').toBoolean(), false);
Expand Down
18 changes: 18 additions & 0 deletions test/Either/Right.js
Expand Up @@ -167,6 +167,24 @@ describe('Right', function() {
'The value at position 1 is not a member of ‘Function’.\n'));
});

it('provides a "reduce" method', function() {
eq(S.Right(5).reduce.length, 2);
eq(S.Right(5).reduce(function(xs, x) { return xs.concat([x]); }, [42]),
[42, 5]);

throws(function() { S.Right().reduce(null, null); },
errorEq(TypeError,
'Invalid value\n' +
'\n' +
'Either#reduce :: Either a b -> Function -> c -> c\n' +
' ^^^^^^^^\n' +
' 1\n' +
'\n' +
'1) null :: Null\n' +
'\n' +
'The value at position 1 is not a member of ‘Function’.\n'));
});

it('provides a "toBoolean" method', function() {
eq(S.Right(42).toBoolean.length, 0);
eq(S.Right(42).toBoolean(), true);
Expand Down

0 comments on commit b149c57

Please sign in to comment.