curryとapplyとprototype.js

1引数

  • apply(f, a) = f(a)
  • curry(f)(a) = f(a)
  • curry(apply)(f)(a) = f(a)
    • curry(apply)は function(f){return f} =idと同等

prototype.jsのcurryはこうなっていない。と言っても対応するapplyがない以上なるならないの問題以前か。ただf.curry()がfそのままのようなので、部分適用という評価は正しいと思う。

複数引数の場合を考えてみると、

2引数(applyがタプル)

  • apply(f, (a, b)) = f(a, b)
  • curry(f)(a)(b) = f(a, b)
  • curry(apply)(f)(a, b) = f(a, b)

2引数(applyが展開)

  • apply(f, a, b) = f(a, b)
  • curry(f)(a)(b) = f(a, b)
  • curry(apply)(f)(a)(b) = f(a, b)

0引数(タプル)

  • apply(f, ()) = f()
  • curry(f)() = f()
  • curry(apply)(f)() = f()

0引数(展開)

  • apply(f) = f()
  • curry(f) = f()
  • curry(apply)(f) = f()

ECMA Scriptのapplyをそのままつかうんだとしたら

  • f.apply(this, [a, b]) = this.f(a, b)
  • f.curry(this)(a)(b) = this.f(a, b)
  • Function.prototype.apply.curry(f)(this)(a, b) = this.f(a, b)

となるようにすべきなのかな

fが一引数の場合を考えると、第二引数は配列でなくてはいけないから

  • Function.prototype.apply.curry(f)(this)([a, b]) = this.f(a, b)

になっちゃうか。つかこのapplyだと等式curry(apply)(f)=fが満たせないな。

  Function.prototype.curry = function () {
    var args = Array.apply(null, arguments);
    var that = args.shift();
    var func = this;
    return function (arg) {
       var nargs = Array.apply(null, args)
       nargs.push(arg);
       if (func.length == nargs.length) {
         return func.apply(that, nargs);
       } else {
         nargs.unshift(that);
         return func.curry.apply(func, nargs);
       }
    }
  }

結局メソッドは無視で、関数版applyを用意し、f.bind(this).curry()...として、扱うべきだろうか。
そして、f.fapply().curry()(a,b) == f(a,b)になるようなって考えたけど、このfapplyってfそのものじゃないか。じゃあ意味なしかな。