Repository: plaid/sanctuary (js)

Issue:
catMaybes :: [Maybe a] -> [a]
<https://hackage.haskell.org/package/base-4.8.1.0/docs/Data-Maybe.html#v:catMaybes>:

> The `catMaybes` function takes a list of `Maybe`s and returns a list of all the `Just` values.


Pull request description:
maybe: add S.catMaybes
Closes #72

`maybe :: b -> (a -> b) -> Maybe a -> b` proved useful in defining this function. I'll rebase this patch once #77 has been merged.


Patch:
diff --git a/index.js b/index.js
index 44421d4..b197d4a 100644
--- a/index.js
+++ b/index.js
@@ -682,10 +682,21 @@
   //. > S.maybe(0, R.length, S.Nothing())
   //. 0
   //. ```
-  S.maybe = def('maybe', [a, Function, Maybe], function(x, f, maybe) {
+  var maybe = S.maybe =
+  def('maybe', [a, Function, Maybe], function(x, f, maybe) {
     return fromMaybe(x, maybe.map(f));
   });
 
+  //# catMaybes :: [Maybe a] -> [a]
+  //.
+  //. Takes a list of Maybes and returns a list containing each Just's value.
+  //.
+  //. ```javascript
+  //. > S.catMaybes([S.Just('foo'), S.Nothing(), S.Just('baz')])
+  //. ["foo", "baz"]
+  //. ```
+  S.catMaybes = def('catMaybes', [Accessible], R.chain(maybe([], R.of)));
+
   //# encase :: (* -> a) -> (* -> Maybe a)
   //.
   //. Takes a function `f` which may throw and returns a curried function


Test patch:
diff --git a/test/index.js b/test/index.js
index 37b3d72..829bb67 100644
--- a/test/index.js
+++ b/test/index.js
@@ -686,6 +686,30 @@ describe('maybe', function() {
 
   });
 
+  describe('catMaybes', function() {
+
+    it('is a unary function', function() {
+      eq(typeof S.catMaybes, 'function');
+      eq(S.catMaybes.length, 1);
+    });
+
+    it('type checks its arguments', function() {
+      assert.throws(function() { S.catMaybes(null); },
+                    errorEq(TypeError,
+                            'The first argument to ‘catMaybes’ ' +
+                            'cannot be null or undefined'));
+    });
+
+    it('returns a list containing the value of each Just', function() {
+      eq(S.catMaybes([]), []);
+      eq(S.catMaybes([S.Nothing(), S.Nothing()]), []);
+      eq(S.catMaybes([S.Nothing(), S.Just('b')]), ['b']);
+      eq(S.catMaybes([S.Just('a'), S.Nothing()]), ['a']);
+      eq(S.catMaybes([S.Just('a'), S.Just('b')]), ['a', 'b']);
+    });
+
+  });
+
   describe('encase', function() {
 
     it('is a unary function', function() {