From ea8b184b84b75013d5b2227381caa10c1558272a Mon Sep 17 00:00:00 2001
From: Travis LaDuke <travisladuke@gmail.com>
Date: Fri, 18 Nov 2016 21:08:12 -0800
Subject: [PATCH] curry2: Add functions curry2, curry3, curry4, curry5.

---
 index.js       | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++
 test/curry2.js | 17 ++++++++++
 test/curry3.js | 19 ++++++++++++
 test/curry4.js | 23 ++++++++++++++
 test/curry5.js | 31 +++++++++++++++++++
 5 files changed, 174 insertions(+)
 create mode 100644 test/curry2.js
 create mode 100644 test/curry3.js
 create mode 100644 test/curry4.js
 create mode 100644 test/curry5.js

diff --git a/index.js b/index.js
index be579657..afcd6f84 100644
--- a/index.js
+++ b/index.js
@@ -300,6 +300,7 @@
   var b = $.TypeVariable('b');
   var c = $.TypeVariable('c');
   var d = $.TypeVariable('d');
+  var e = $.TypeVariable('e');
   var f = $.TypeVariable('f');
   var l = $.TypeVariable('l');
   var r = $.TypeVariable('r');
@@ -632,6 +633,89 @@
 
   //. ### Function
 
+  //# curry2 :: ((a, b) -> c) -> a -> b -> c
+  //.
+  //. Curries the given binary function.
+  //.
+  //. ```javascript
+  //. > R.map(S.curry2(Math.pow)(10), [1, 2, 3])
+  //. [10, 100, 1000]
+  //.
+  //. > R.map(S.curry2(Math.pow, 10), [1, 2, 3])
+  //. [10, 100, 1000]
+  //. ```
+  function curry2(f, x, y) {
+    return f(x, y);
+  }
+  S.curry2 = def('curry2', {}, [$.Function, a, b, c], curry2);
+
+  //# curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
+  //.
+  //. Curries the given ternary function.
+  //.
+  //. ```javascript
+  //. > global.replaceString = S.curry3((what, replacement, string) =>
+  //. .   string.replace(what, replacement)
+  //. . )
+  //. replaceString
+  //.
+  //. > replaceString('banana')('orange')('banana icecream')
+  //. 'orange icecream'
+  //.
+  //. > replaceString('banana', 'orange', 'banana icecream')
+  //. 'orange icecream'
+  //. ```
+  function curry3(f, x, y, z) {
+    return f(x, y, z);
+  }
+  S.curry3 = def('curry3', {}, [$.Function, a, b, c, d], curry3);
+
+  //# curry4 :: ((a, b, c, d) -> e) -> a -> b -> c -> d -> e
+  //.
+  //. Curries the given quaternary function.
+  //.
+  //. ```javascript
+  //. > global.createRect = S.curry4((x, y, width, height) =>
+  //. .   ({x, y, width, height})
+  //. . )
+  //. createRect
+  //.
+  //. > createRect(0)(0)(10)(10)
+  //. {x: 0, y: 0, width: 10, height: 10}
+  //.
+  //. > createRect(0, 0, 10, 10)
+  //. {x: 0, y: 0, width: 10, height: 10}
+  //. ```
+  function curry4(f, w, x, y, z) {
+    return f(w, x, y, z);
+  }
+  S.curry4 = def('curry4', {}, [$.Function, a, b, c, d, e], curry4);
+
+  //# curry5 :: ((a, b, c, d, e) -> f) -> a -> b -> c -> d -> e -> f
+  //.
+  //. Curries the given quinary function.
+  //.
+  //. ```javascript
+  //. > global.toUrl = S.curry5((protocol, creds, hostname, port, pathname) =>
+  //. .   protocol + '//' +
+  //. .   S.maybe('', _ => _.username + ':' + _.password + '@', creds) +
+  //. .   hostname +
+  //. .   S.maybe('', S.concat(':'), port) +
+  //. .   pathname
+  //. . )
+  //. toUrl
+  //.
+  //. > toUrl('https:')(S.Nothing)('example.com')(S.Just('443'))('/foo/bar')
+  //. 'https://example.com:443/foo/bar'
+  //.
+  //. > toUrl('https:', S.Nothing, 'example.com', S.Just('443'), '/foo/bar')
+  //. 'https://example.com:443/foo/bar'
+  //. ```
+  function curry5(f, v, w, x, y, z) {
+    return f(v, w, x, y, z);
+  }
+  S.curry5 = def('curry5', {}, [$.Function, a, b, c, d, e, r], curry5);
+
   //# flip :: ((a, b) -> c) -> b -> a -> c
   //.
   //. Takes a binary function and two values, and returns the result of
diff --git a/test/curry2.js b/test/curry2.js
new file mode 100644
index 00000000..5c2a95a5
--- /dev/null
+++ b/test/curry2.js
@@ -0,0 +1,17 @@
+'use strict';
+
+var S = require('..');
+
+var eq = require('./internal/eq');
+
+
+test('curry2', function() {
+
+  eq(typeof S.curry2, 'function');
+  eq(S.curry2.length, 3);
+
+  var curried = S.curry2(function(x, y) { return x + y; });
+  eq(curried(1, 2), 3);
+  eq(curried(1)(2), 3);
+
+});
diff --git a/test/curry3.js b/test/curry3.js
new file mode 100644
index 00000000..f9ba80f5
--- /dev/null
+++ b/test/curry3.js
@@ -0,0 +1,19 @@
+'use strict';
+
+var S = require('..');
+
+var eq = require('./internal/eq');
+
+
+test('curry3', function() {
+
+  eq(typeof S.curry3, 'function');
+  eq(S.curry3.length, 4);
+
+  var curried = S.curry3(function(x, y, z) { return x + y + z; });
+  eq(curried(1, 2, 3), 6);
+  eq(curried(1, 2)(3), 6);
+  eq(curried(1)(2, 3), 6);
+  eq(curried(1)(2)(3), 6);
+
+});
diff --git a/test/curry4.js b/test/curry4.js
new file mode 100644
index 00000000..ec12b878
--- /dev/null
+++ b/test/curry4.js
@@ -0,0 +1,23 @@
+'use strict';
+
+var S = require('..');
+
+var eq = require('./internal/eq');
+
+
+test('curry4', function() {
+
+  eq(typeof S.curry4, 'function');
+  eq(S.curry4.length, 5);
+
+  var curried = S.curry4(function(w, x, y, z) { return w + x + y + z; });
+  eq(curried(1, 2, 3, 4), 10);
+  eq(curried(1, 2, 3)(4), 10);
+  eq(curried(1, 2)(3, 4), 10);
+  eq(curried(1, 2)(3)(4), 10);
+  eq(curried(1)(2, 3, 4), 10);
+  eq(curried(1)(2, 3)(4), 10);
+  eq(curried(1)(2)(3, 4), 10);
+  eq(curried(1)(2)(3)(4), 10);
+
+});
diff --git a/test/curry5.js b/test/curry5.js
new file mode 100644
index 00000000..0a5a8238
--- /dev/null
+++ b/test/curry5.js
@@ -0,0 +1,31 @@
+'use strict';
+
+var S = require('..');
+
+var eq = require('./internal/eq');
+
+
+test('curry5', function() {
+
+  eq(typeof S.curry5, 'function');
+  eq(S.curry5.length, 6);
+
+  var curried = S.curry5(function(v, w, x, y, z) { return v + w + x + y + z; });
+  eq(curried(1, 2, 3, 4, 5), 15);
+  eq(curried(1, 2, 3, 4)(5), 15);
+  eq(curried(1, 2, 3)(4, 5), 15);
+  eq(curried(1, 2, 3)(4)(5), 15);
+  eq(curried(1, 2)(3, 4, 5), 15);
+  eq(curried(1, 2)(3, 4)(5), 15);
+  eq(curried(1, 2)(3)(4, 5), 15);
+  eq(curried(1, 2)(3)(4)(5), 15);
+  eq(curried(1)(2, 3, 4, 5), 15);
+  eq(curried(1)(2, 3, 4)(5), 15);
+  eq(curried(1)(2, 3)(4, 5), 15);
+  eq(curried(1)(2, 3)(4)(5), 15);
+  eq(curried(1)(2)(3, 4, 5), 15);
+  eq(curried(1)(2)(3, 4)(5), 15);
+  eq(curried(1)(2)(3)(4, 5), 15);
+  eq(curried(1)(2)(3)(4)(5), 15);
+
+});