//:: ((a, b) => c) => (a) => (b) => c
export const curry = (fn, ...args) => {
  const c = (fnArgs) => {
    if (fnArgs.length >= fn.length) {
      return fn.apply(this, fnArgs);
    }
    return (...cArgs) => c([...fnArgs, ...cArgs]);
  };
  return c(args);
};

//:: ((...args) => b?, args:[ Any ]) => b
export const apply = curry((fn, args) => fn.apply(null, args));

//:: (a => b => c) => b => a => c
export const flip = curry((fn, x, y) => fn(y, x));

export const over = curry((f, g, x, y) => f((g(x)), (g(y))));

//:: ((a) => b) => (a) => b
export const memoize = (fn) => {
  let memo = {};
  return (...args) => {
    const key = args.map((arg) => arg + typeof arg).join('');
    return memo[key] || (memo[key] = fn.apply(null, args));
  };
};

//:: (...Function) => Function
export const compose = (...fns) =>
  (...args) =>
    fns.reduce((memo, fn, i) => [fn.apply(this, memo)], args)[0];

// aliases

export const memoise = memoize;

export default {
  curry,
  apply,
  flip,
  over,
  memoize,
  memoise,
  compose
};

@@ -1,14 +1,31 @@
 //
+           curry 
 :: ((a, b) =
@@ -27,29 +27,25 @@
  b) 
-=
+-
 %3E c) 
-=%3E (a) =%3E (b) =
+-%3E a -%3E b -
 %3E c%0A
@@ -279,43 +279,29 @@
 :: (
-(...args) =%3E b?, args:%5B Any %5D) =
+%5Ba%5D -%3E b?, %5Ba%5D) -
 %3E b
+?
 %0Aexp
@@ -374,30 +374,30 @@
  (a 
-=
+-
 %3E b 
-=
+-
 %3E c) 
-=
+-
 %3E b 
-=
+-
 %3E a 
-=
+-
 %3E c%0A
@@ -521,26 +521,22 @@
 :: (
-(a) =
+a -
 %3E b) 
-=%3E (a) =
+-%3E a -
 %3E b%0A
@@ -750,32 +750,29 @@
 :: (
-...Function) =%3E Function
+%5Ba -%3E b?%5D) -%3E a -%3E b?
 %0Aexp

annotate Func module functions