Skip to content

Commit

Permalink
Merge pull request #3 from plaid/dc-bind
Browse files Browse the repository at this point in the history
monad: remove S.bind and S.then in favour of R.chain compatibility
  • Loading branch information
davidchambers committed Feb 2, 2015
2 parents 8e44934 + 3304919 commit cc93a47
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 105 deletions.
30 changes: 10 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
}
extend(Nothing, Maybe);

// Nothing#chain :: (a -> m b) -> m b
Nothing.prototype.chain = function(f) { // jshint ignore:line
return this;
};

// Nothing#equals :: Maybe a -> Boolean
Nothing.prototype.equals = function(maybe) {
return maybe instanceof Nothing;
Expand All @@ -79,6 +84,11 @@
}
extend(Just, Maybe);

// Just#chain :: (a -> m b) -> m b
Just.prototype.chain = function(f) {
return f(this.value);
};

// Just#equals :: Maybe a -> Boolean
Just.prototype.equals = function(maybe) {
return maybe instanceof Just && maybe.value === this.value;
Expand Down Expand Up @@ -167,24 +177,6 @@
}
});

// monad /////////////////////////////////////////////////////////////////

// bind :: m a -> (a -> m b) -> m b
var bind = curry(function(m, f) {
if (isArray(m)) {
return m.length > 0 ? f(m[0]) : m;
} else if (m.type === Maybe) {
return m instanceof Just ? f(m.value) : m;
} else {
throw new TypeError('Pattern match failure');
}
});

// then :: (a -> m b) -> m a -> m b
var then = curry(function(f, m) {
return bind(m, f);
});

// control ///////////////////////////////////////////////////////////////

// or :: f a -> f a -> f a
Expand Down Expand Up @@ -265,7 +257,6 @@
Nothing: Nothing,
Right: Right,
at: at,
bind: bind,
either: either,
get: get,
head: head,
Expand All @@ -277,7 +268,6 @@
parseInt: parseInt_,
parseJson: parseJson,
tail: tail,
then: then,
toMaybe: toMaybe,
};

Expand Down
97 changes: 12 additions & 85 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ describe('maybe', function() {
eq(nothing.type, S.Maybe);
});

it('provides a "chain" method', function() {
var nothing = S.Nothing();
eq(nothing.chain.length, 1);
eq(nothing.chain(S.head), nothing);
});

it('provides an "equals" method', function() {
var nothing = S.Nothing();
eq(nothing.equals.length, 1);
Expand Down Expand Up @@ -92,6 +98,12 @@ describe('maybe', function() {
eq(just.type, S.Maybe);
});

it('provides a "chain" method', function() {
var just = S.Just([1, 2, 3]);
eq(just.chain.length, 1);
assert(just.chain(S.head).equals(S.Just(1)));
});

it('provides an "equals" method', function() {
var just = S.Just(42);
eq(just.equals.length, 1);
Expand Down Expand Up @@ -289,91 +301,6 @@ describe('either', function() {

});

describe('monad', function() {

describe('bind', function() {

// toNumber :: String -> [Number]
var toNumber = function(s) {
var n = parseFloat(s);
return n === n ? [n] : [];
};

it('can be applied to empty array', function() {
var m = S.bind([], toNumber);
eq(Object.prototype.toString.call(m), '[object Array]');
eq(m.length, 0);
});

it('can be applied to singleton array', function() {
var m = S.bind(['42'], toNumber);
eq(Object.prototype.toString.call(m), '[object Array]');
eq(m.length, 1);
eq(m[0], 42);

var m2 = S.bind(['xxx'], toNumber);
eq(Object.prototype.toString.call(m2), '[object Array]');
eq(m2.length, 0);
});

it('can be applied to a Nothing', function() {
var m = S.bind(S.Nothing(), S.head);
assert(m.equals(S.Nothing()));
});

it('can be applied to a Just', function() {
var m = S.bind(S.Just([42, 21]), S.head);
assert(m.equals(S.Just(42)));
});

it('throws if applied to a non-monad', function() {
assert.throws(
function() { S.bind(/xxx/, S.head); },
function(err) {
return err instanceof TypeError &&
err.message === 'Pattern match failure';
}
);
});

it('is curried', function() {
var maybe = S.bind(S.Just([42, 21]))(S.head);
assert(maybe.equals(S.Just(42)));
});

});

describe('then', function() {

it('can be applied to a Nothing', function() {
var maybe = S.then(S.head, S.Nothing());
assert(maybe.equals(S.Nothing()));
});

it('can be applied to a Just', function() {
var maybe = S.then(S.head, S.Just([42, 21]));
assert(maybe.equals(S.Just(42)));
});

it('throws if applied to a value of non-monad', function() {
assert.throws(
function() { S.then(S.head, /xxx/); },
function(err) {
return err instanceof TypeError &&
err.message === 'Pattern match failure';
}
);
});

it('is curried', function() {
var maybe = S.then(S.head)(S.Just([42, 21]));
assert(maybe.equals(S.Just(42)));
});

});

});

describe('control', function() {

describe('or', function() {
Expand Down

0 comments on commit cc93a47

Please sign in to comment.