Haskell Hackathon

  • 割と設計に手を入れたいところがたくさんあるけど、リファクタリングと移植を同時にやるとバグったときに大変なのでまずはあんまり大きな修正は入れずに実装。
  • @15:40
>>> infer(FunApp(Ident(":"), Ident("5")))
(: 5) : [t5=((List [t4=Int]) -> (List [t4=Int]))]
  • つまり((:) 5)の型は[Int] -> [Int]ということ。Haskellの(: 5)と結果が違うのはHaskellの:が2項演算子だから。
  • @15:59
(\n -> ((: n) ((: 5) []))) : ([t6=Int] -> [t10=(List [t4=Int])])
  • つまり、引数を整数のリストに追加して返す関数を作ったら、その引数は整数ではないといけない、という推論ができている。Preludeで試すと下のようになる。
Prelude> :t \n -> n:5:[]
\n -> n:5:[] :: (Num a) => a -> [a]

手書きした構文木は下記

    ast = Lambda(
        Ident("n"),
        FunApp(
            FunApp(
                Ident(":"),
                Ident("n")),
            FunApp(
                FunApp(Ident(":"), Ident("5")),
                Ident("[]"))))

    infer(ast)

そろそろ構文木の手書きも面倒になってきたぞ。

  • @16:24
  • この前のPythonSchemeを作ったときのコードを使って構文木の手書きを楽にした。
>>> parse("(\ n -> ((: n) ((: 5) [])))")
['\\', 'n', '->', [[':', 'n'], [[':', '5'], '[]']]]
[[':', 'n'], [[':', '5'], '[]']]
[':', 'n']
:
n
[[':', '5'], '[]']
[':', '5']
:
5
[]
(\n -> ((: n) ((: 5) [])))
>>> infer(_)
(\n -> ((: n) ((: 5) []))) : (Int -> (List Int))
  • あと解決済みの型変数まで表示されて「([t5=Int] -> [t9=(List [t4=Int])])」とか出るのは鬱陶しいのでオプションで切り換えられるようにした。(Int -> (List Int))って出るようになった。
  • 関数適用が常に1引数なんだけど、書くときにそれじゃ面倒なんでカリー化するようにした。
>>> parse("(f 1 2 3 4 5)")
(((((f 1) 2) 3) 4) 5)
  • @21:30
>>> infer(parse("(let (f = (\ x -> x)) in (pair (f 3) (f true)))"))
(let (f = (\x -> x)) in ((pair (f 3)) (f true))) : (Pair Int Bool)