Haskell Hackathon

とりあえず D BOF は後で。

http://shinh.skr.jp/koneta/dhc.tgz

眠いなーと思いつつ D BOF の後で行った。たぶん2時くらいについた。なんかみんな飯喰ってたのでだべる。チャットから時間を起こそう。

とりあえずパーサとかどうでもいいので構文木を喰わせる実装にすることは決まってたので、 Haskell についてあれこれ考えてから S 式パーサを書いた。 3:30

んで型をなんかするのを作った。なんか int, bool, string, IO という 4 つの型があって、そのどれかか、決定できないかを調べる程度。 IO はモナドでもなんでもない。 5:13

Hello world 動いた。 6:13

(
 (funcdef gen_hello (v) (let x (++ "Hello, " v) x))
 (funcdef hello () (putStr (gen_hello "world!\n")))
 (funcdef main () (hello))
)

if とか作って再帰大丈夫にして fizzbuzz 動いた。 7:30

(
 (funcdef fb (n) (if (== (mod n 15) 0) (putStr "FizzBuzz\n")
                   (if (== (mod n 5) 0) (putStr "Buzz\n")
                     (if (== (mod n 3) 0) (putStr "Fizz\n")
                       (>> (putInt n) (putStr "\n"))))))
 (funcdef fizzbuzz(n)
          (if (== n 101) (return) (>> (fb n) (fizzbuzz (+ n 1)))))
 (funcdef main() (fizzbuzz 1))
)

そっからがなんか辛くて遅延評価をやろうとたらい回し関数を書いてみてちょっとバグを潰す。

(
 (funcdef tarai (x y z)
          (if (<= x y) y
            (tarai (tarai (- x 1) y z)
                   (tarai (- y 1) z x)
                   (tarai (- z 1) x y))))
 (funcdef main ()
          (>> (putInt (tarai 52 122 10)) (putStr "\n")))
)

遅延評価がなかなか実装できなくて苦しんだ。 10:26 にたらい高速化終了。

あとは多相関数なんとかしたいなーと思ったけど現状の構造をかなりいじらにゃならんと気付いた。けどまぁ id はインチキで通るようになってます。

(
 (funcdef id (x) x)
 (funcdef main ()
   (putStr (id "hoge\n")))
)

ちなみにたらい回し関数はこんな D コードに変換される。

import rt;
extern(C) int _tarai(Thunk!(int) x,Thunk!(int) y,Thunk!(int) z) {
 return thunk(thunk({ return ___60__61(thunk(x), thunk(y));})() ? thunk(y) : thunk({ return _tarai(thunk({ return _tarai(thunk({ return ___45(thunk(x), thunk(1));}), thunk(y), thunk(z));}), thunk({ return _tarai(thunk({ return ___45(thunk(y), thunk(1));}), thunk(z), thunk(x));}), thunk({ return _tarai(thunk({ return ___45(thunk(z), thunk(1));}), thunk(x), thunk(y));}));}))();
}
extern(C) IO _main() {
 return thunk({ return ___62__62(thunk({ return _putInt(thunk({ return _tarai(thunk(52), thunk(122), thunk(10));}));}), thunk({ return _putStr(thunk(new Thunk!(string)("\n")));}));})();
}

全く読めん。 Thunk はこんな感じになった。久々にメタなことやったのですごい時間かかった…

class ThunkBase {}

class Thunk(T) : ThunkBase {
    this(T t0) {
        t = t0;
        done = true;
    }
    this(Thunk t0) {
        t = t0.t;
        dg = t0.dg;
        done = t0.done;
    }
    this(T delegate() dg0) {
        dg = dg0;
    }
    T opCall() {
        if (done) return t;
        done = true;
        return t = dg();
    }
    T t;
    T delegate() dg;
    bool done;
    static const bool is_thunk = true;
}

template ThunkType(T) {
    static if (is(T : ThunkBase)) {
        alias T ThunkType;
    }
    else static if (is(T R == return)) {
        alias Thunk!(R) ThunkType;
    }
    else {
        alias Thunk!(T) ThunkType;
    }
}

template thunk(T) {
    ThunkType!(T) thunk(T t) { return new ThunkType!(T)(t); }
}

お疲れさまでした。会場提供やら運営やらありがとうございました。 > サイボウズ☆ラボ

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h