Skip to content

Commit

Permalink
maybe: implement Semigroup and Monoid
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchambers committed Feb 25, 2015
1 parent 0e8455a commit 7caf545
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
17 changes: 17 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,18 @@
throw new Error('Cannot instantiate Maybe');
}

// Maybe.empty :: -> m a
Maybe.empty = function() {
return new Nothing();
};

// Maybe.of :: a -> m a
Maybe.of = function(x) {
return new Just(x);
};

Maybe.prototype.empty = Maybe.empty;

Maybe.prototype.of = Maybe.of;

Maybe.prototype.type = Maybe;
Expand All @@ -72,6 +79,11 @@
return this;
};

// Nothing#concat :: m a -> m a
Nothing.prototype.concat = function(maybe) {
return maybe;
};

// Nothing#equals :: Maybe a -> Boolean
Nothing.prototype.equals = function(maybe) {
return maybe instanceof Nothing;
Expand Down Expand Up @@ -106,6 +118,11 @@
return f(this.value);
};

// Just#concat :: m a -> m a
Just.prototype.concat = function(maybe) {
return maybe instanceof Just ? Just(this.value.concat(maybe.value)) : this;
};

// Just#equals :: Maybe a -> Boolean
Just.prototype.equals = function(maybe) {
return maybe instanceof Just && maybe.value === this.value;
Expand Down
52 changes: 52 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ describe('maybe', function() {
eq(nothing.chain(S.head), nothing);
});

it('provides a "concat" method', function() {
var nothing = S.Nothing();
eq(nothing.concat.length, 1);
assert(nothing.concat(S.Nothing()).equals(S.Nothing()));
assert(nothing.concat(S.Just('foo')).equals(S.Just('foo')));
});

it('provides an "equals" method', function() {
var nothing = S.Nothing();
eq(nothing.equals.length, 1);
Expand All @@ -94,6 +101,25 @@ describe('maybe', function() {
eq(S.Nothing().or(just), just);
});

it('implements Semigroup', function() {
var a = S.Nothing();
var b = S.Nothing();
var c = S.Nothing();

// associativity
assert(a.concat(b).concat(c).equals(a.concat(b.concat(c))));
});

it('implements Monoid', function() {
var a = S.Nothing();

// left identity
assert(a.empty().concat(a).equals(a));

// right identity
assert(a.concat(a.empty()).equals(a));
});

it('implements Functor', function() {
var a = S.Nothing();
var f = inc;
Expand Down Expand Up @@ -195,6 +221,13 @@ describe('maybe', function() {
assert(just.chain(S.head).equals(S.Just(1)));
});

it('provides a "concat" method', function() {
var just = S.Just('foo');
eq(just.concat.length, 1);
assert(just.concat(S.Nothing()).equals(S.Just('foo')));
assert(just.concat(S.Just('bar')).equals(S.Just('foobar')));
});

it('provides an "equals" method', function() {
var just = S.Just(42);
eq(just.equals.length, 1);
Expand All @@ -218,6 +251,25 @@ describe('maybe', function() {
eq(just.or(S.Just(42)), just);
});

it('implements Semigroup', function() {
var a = S.Just('foo');
var b = S.Just('bar');
var c = S.Just('baz');

// associativity
assert(a.concat(b).concat(c).equals(a.concat(b.concat(c))));
});

it('implements Monoid', function() {
var a = S.Just([1, 2, 3]);

// left identity
assert(a.empty().concat(a).equals(a));

// right identity
assert(a.concat(a.empty()).equals(a));
});

it('implements Functor', function() {
var a = S.Just(7);
var f = inc;
Expand Down

0 comments on commit 7caf545

Please sign in to comment.