Repository: sanctuary-js/sanctuary
Pull request #184 (2016-04-19 21:47:33)

Add S.append
This adds S.append as suggested by #145 

So this is my first contribution and I just naively implemented it as `a -> [a] -> [a]`.

davidchambers: It looks as though your tests disappeared in the rebase!

gilligan: @davidchambers ugh.. tests added again. This whole PR took much longer than I would have anticipated ;)
Avaq: Looks good to me, though I haven't kept up with the discussions leading up to this point. I'll leave the final call to @davidchambers.
gilligan: Are we good to go now? :-) *fingers crossed*
davidchambers: Delete the stray line and I'll merge. :)


Patch:
diff --git a/index.js b/index.js
index 44023d8..ff05c6d 100644
--- a/index.js
+++ b/index.js
@@ -2344,6 +2344,24 @@
 
   //. ### Array
 
+  //# append :: a -> Array a -> Array a
+  //.
+  //. Takes a value of any type and an array of values of that type, and
+  //. returns the result of appending the value to the array.
+  //.
+  //. ```javascript
+  //. > S.append(3, [1, 2])
+  //. [1, 2, 3]
+  //.
+  //. > S.append([3, 4], [[1], [2]])
+  //. [[1], [2], [3, 4]]
+  //. ```
+  S.append =
+  def('append',
+      {},
+      [a, $.Array(a), $.Array(a)],
+      function(x, xs) { return xs.concat([x]); });
+
   //# find :: (a -> Boolean) -> Array a -> Maybe a
   //.
   //. Takes a predicate and an array and returns Just the leftmost element of


Test patch:
diff --git a/test/append.js b/test/append.js
new file mode 100644
index 0000000..f668a1a
--- /dev/null
+++ b/test/append.js
@@ -0,0 +1,64 @@
+'use strict';
+
+var throws = require('assert').throws;
+
+var errorEq = require('./utils').errorEq;
+var eq = require('./utils').eq;
+var S = require('..');
+
+
+describe('append', function() {
+
+   it('is a binary function', function() {
+     eq(typeof S.append, 'function');
+     eq(S.append.length, 2);
+   });
+
+   it('type checks its arguments', function() {
+     throws(function() { S.append('c', 'ab'); },
+            errorEq(TypeError,
+                    'Invalid value\n' +
+                    '\n' +
+                    'append :: a -> Array a -> Array a\n' +
+                    '               ^^^^^^^\n' +
+                    '                  1\n' +
+                    '\n' +
+                    '1)  "ab" :: String\n' +
+                    '\n' +
+                    'The value at position 1 is not a member of ‘Array a’.\n'));
+
+     throws(function() { S.append('c', [1, 2]); },
+            errorEq(TypeError,
+                    'Type-variable constraint violation\n' +
+                    '\n' +
+                    'append :: a -> Array a -> Array a\n' +
+                    '          ^          ^\n' +
+                    '          1          2\n' +
+                    '\n' +
+                    '1)  "c" :: String\n' +
+                    '\n' +
+                    '2)  1 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' +
+                    '    2 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer, ValidNumber\n' +
+                    '\n' +
+                    'Since there is no type of which all the above values are members, the type-variable constraint has been violated.\n'));
+   });
+
+  it('adds the element to the end of the list', function() {
+    eq(S.append('c', ['a', 'b']), ['a', 'b', 'c']);
+    eq(S.append({x: 3}, [{x: 1}, {x: 2}]), [{x: 1}, {x: 2}, {x: 3}]);
+  });
+
+  it('adds a list to a list of lists', function() {
+    eq(S.append([3, 4], [[1], [2]]), [[1], [2], [3, 4]]);
+  });
+
+  it('works on empty list', function() {
+    eq(S.append(1, []), [1]);
+  });
+
+  it('is curried', function() {
+    eq(S.append('c').length, 1);
+    eq(S.append('c')(['a', 'b']), ['a', 'b', 'c']);
+  });
+
+});