Skip to content

Instantly share code, notes, and snippets.

@susisu
Created February 20, 2015 08:32
Show Gist options
  • Save susisu/7b58f7023c931fb06528 to your computer and use it in GitHub Desktop.
Save susisu/7b58f7023c931fb06528 to your computer and use it in GitHub Desktop.
みんなだいすきラムダ式

みんなだいすきラムダ式.

function Lambda(argName, body) {
    this.argName = argName;
    this.body    = body;
}

Lambda.prototype.eval = function (env) {
    var argName = this.argName;
    var body    = this.body;
    return function (_arg) {
        var local = Object.create(env);
        local[argName] = _arg;
        return body.eval(local);
    };
};

function Application(func, arg) {
    this.func = func;
    this.arg  = arg;
}

Application.prototype.eval = function (env) {
    var _func = this.func.eval(env);
    var _arg  = this.arg.eval(env);
    return _func(_arg);
};

function Variable(name) {
    this.name = name;
}

Variable.prototype.eval = function (env) {
    return env[this.name];
};

定番の自然数.

var global = Object.create(null);

// zero = λf x. x
global["zero"] = new Lambda("f", new Lambda("x", new Variable("x"))).eval(global);
// succ = λn f x. f (n f x)
global["succ"] = new Lambda("n",
        new Lambda("f", new Lambda("x",
            new Application(new Variable("f"),
                new Application(
                    new Application(new Variable("n"), new Variable("f")),
                    new Variable("x")
                )
            )
        ))
    ).eval(global);
// one = succ zero
// two = succ one
// ...
global["one"]   = new Application(new Variable("succ"), new Variable("zero")).eval(global);
global["two"]   = new Application(new Variable("succ"), new Variable("one")).eval(global);
global["three"] = new Application(new Variable("succ"), new Variable("two")).eval(global);
global["four"]  = new Application(new Variable("succ"), new Variable("three")).eval(global);
global["five"]  = new Application(new Variable("succ"), new Variable("four")).eval(global);

// plus = λm n f x. m f (n f x)
global["plus"] =
    new Lambda("m", new Lambda("n",
        new Lambda("f", new Lambda("x",
            new Application(
                new Application(new Variable("m"), new Variable("f")),
                new Application(
                    new Application(new Variable("n"), new Variable("f")),
                    new Variable("x")
                )
            )
        ))
    )).eval(global);

// foo = plus three five
global["foo"] =
    new Application(
        new Application(new Variable("plus"), new Variable("three")),
        new Variable("five")
    ).eval(global);

ちゃんと計算できてるか確認.

function Literal(val) {
    this.val = val;
}

Literal.prototype.eval = function (env) {
    return this.val;
};

global["+1"] = new Literal(function (n) { return n + 1; }).eval(global);
global["0"] = new Literal(0).eval(global);
console.log(
    new Application(
        new Application(new Variable("foo"), new Variable("+1")),
        new Variable("0")
    ).eval(global)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment