Repository: sanctuary-js/sanctuary (js)

Issue:
S.pluck documentation is incorrect
The documentation for [`pluck`](https://github.com/sanctuary-js/sanctuary/blob/0853d0a592233fd602e8167760e33812d1870fa8/index.js#L3044-L3045) states that it is equivalent to `map(prop(k), xs)`. This is only the case if `xs` is an `Array`.

Either the documentation should be changed, or `pluck` should be updated to handle Functors in general (matching [`R.pluck`](http://ramdajs.com/docs/#pluck)'s behavior).

Incidentally, `R.pluck` works for Arrays and indices as well as Objects and keys (for obvious reasons).

Pull request description:
array: generalize S.pluck
Fixes #381


Patch:
diff --git a/index.js b/index.js
index bf119bd..d252df7 100644
--- a/index.js
+++ b/index.js
@@ -3209,7 +3209,7 @@
   }
   S.find = def('find', {}, [Pred(a), $.Array(a), $Maybe(a)], find);
 
-  //# pluck :: Accessible a => String -> Array a -> Array b
+  //# pluck :: (Accessible a, Functor f) => String -> f a -> f b
   //.
   //. Combines [`map`](#map) and [`prop`](#prop). `pluck(k, xs)` is equivalent
   //. to `map(prop(k), xs)`.
@@ -3217,19 +3217,21 @@
   //. ```javascript
   //. > S.pluck('x', [{x: 1}, {x: 2}, {x: 3}])
   //. [1, 2, 3]
+  //.
+  //. > S.pluck('x', S.Just({x: 1, y: 2, z: 3}))
+  //. Just(1)
   //. ```
   function pluck(key, xs) {
-    return xs.map(function(x, idx) {
+    return Z.map(function(x) {
       if (key in Object(x)) return x[key];
-      throw new TypeError('‘pluck’ expected object at index ' + idx +
-                          ' to have a property named ‘' + key + '’; ' +
-                          Z.toString(x) + ' does not');
-    });
+      throw new TypeError('‘pluck’ expected object to have a property named ' +
+                          '‘' + key + '’; ' + Z.toString(x) + ' does not');
+    }, xs);
   }
   S.pluck =
   def('pluck',
-      {a: [Accessible]},
-      [$.String, $.Array(a), $.Array(b)],
+      {a: [Accessible], f: [Z.Functor]},
+      [$.String, f(a), f(b)],
       pluck);
 
   //# unfoldr :: (b -> Maybe (Pair a b)) -> b -> Array a


Test patch:
diff --git a/test/pluck.js b/test/pluck.js
index 05c7062..58106ec 100644
--- a/test/pluck.js
+++ b/test/pluck.js
@@ -10,13 +10,16 @@ test('pluck', function() {
 
   eq(typeof S.pluck, 'function');
   eq(S.pluck.length, 2);
-  eq(S.pluck.toString(), 'pluck :: Accessible a => String -> Array a -> Array b');
+  eq(S.pluck.toString(), 'pluck :: (Accessible a, Functor f) => String -> f a -> f b');
 
   throws(function() { S.pluck('a', [{a: 1}, {b: 2}]); },
          TypeError,
-         '‘pluck’ expected object at index 1 to have a property named ‘a’; {"b": 2} does not');
+         '‘pluck’ expected object to have a property named ‘a’; {"b": 2} does not');
 
   eq(S.pluck('x', []), []);
   eq(S.pluck('x', [{x: 1}, {x: 2}, {x: 3}]), [1, 2, 3]);
 
+  eq(S.pluck('x', S.Nothing), S.Nothing);
+  eq(S.pluck('x', S.Just({x: 1, y: 2, z: 3})), S.Just(1));
+
 });