Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A brief introduction to type inference

A brief introduction to type inference

We present a brief introduction to what "type inference" is and how it works, in 5 minutes! This talk will take place in VRCLT #2. Please visit their website https://vrc-lt.github.io/ for more information.

cannorin

June 14, 2019
Tweet

More Decks by cannorin

Other Decks in Programming

Transcript

  1. 1 / 42
    VRCLT #2
    型推論を支える技術
    cannorin

    View Slide

  2. 2 / 42

    ● Twitter: @cannorin_vrc
    ● Study: 数理論理学,プログラム言語の理論
    ● Job: F# プログラマ(アルバイト)

    View Slide

  3. 3 / 42
    不毛な型推論バトル
    ● C#/Java の var みたいなやつでしょ
    ● Python も型書かなくていいじゃん
    ● そんな最近出てきた機能知らない

    View Slide

  4. 4 / 42
    不毛な型推論バトル ←こわい
    ● C#/Java の var みたいなやつでしょ
    → あいつらはクソザコ!
    ● Python も型書かなくていいじゃん
    → 動的型付けと一緒にするな!
    ● そんな最近出てきた機能知らない
    → 昔からあるし!

    View Slide

  5. 5 / 42
    なぜ繰り返されるのか
    ● 型推論とは一体なんなのか理解されていない
    ● 型推論の仕組みが知られてない
    ● わからないものは怖がられがち

    View Slide

  6. 6 / 42
    なぜ繰り返されるのか
    ● 型推論とは一体なんなのか理解されていない
    (動的型付けとの違いがわからない)
    ● 型推論の仕組みが知られてない
    ( C#/Java の var との違いがわからない)
    ● わからないものは怖がられがち
    (一般にアカデミアの人間は怖がられがち)

    View Slide

  7. 7 / 42
    → 今回の目標!
    ● 型推論とは一体なんなのか説明する
    ● 型推論の仕組みを簡単に解説する
    ● わかったつもりになってもらう

    View Slide

  8. 8 / 42
    1 型推論ってそもそも何?
    ● 主に静的型付き言語をターゲットとする

    View Slide

  9. 9 / 42
    1 型推論ってそもそも何?
    ● 主に静的型付き言語をターゲットとする
    ● 変数・関数の型がほとんど or 全く書かれていない
    コードに

    View Slide

  10. 10 / 42
    1 型推論ってそもそも何?
    ● 主に静的型付き言語をターゲットとする
    ● 変数・関数の型がほとんど or 全く書かれていない
    コードに
    ● もっとも汎用的な正しい型を当てはめる手法

    View Slide

  11. 11 / 42
    1.1 要するに
    let-function add_two (x : int) : int =
    + x 2
    let-function apply_twice
    (f : int → int) (x : int) : int =
    f (f x)
    let-value foo : int =
    apply_twice add_two 0
    もともとはこういう言語

    View Slide

  12. 12 / 42
    1.1 要するに
    let-function add_two (x : int) : int =
    + x 2
    let-function apply_twice
    (f : int → int) (x : int) : int =
    f (f x)
    let-value foo : int =
    apply_twice add_two 0
    プログラマが型を書かなくても

    View Slide

  13. 13 / 42
    1.1 要するに
    let-function add_two (x : int) : int =
    + x 2
    let-function apply_twice
    (f : int → int) (x : int) : int =
    f (f x)
    let-value foo : int = (←C#/Java はここしかできない )
    apply_twice add_two 0
    自動で最適な型をつけてくれる

    View Slide

  14. 14 / 42
    1.2 型推論の特長
    ● 主に静的型付き言語をターゲットとする
    ● 変数・関数の型がほとんど or 全く書かれていない
    コードに
    ● もっとも汎用的な正しい型を当てはめる手法

    View Slide

  15. 15 / 42
    1.2 型推論の特長
    ● 主に静的型付き言語をターゲットとする
    → 厳格な型チェックによる利点はそのまま
    ● 変数・関数の型がほとんど or 全く書かれていない
    コードに
    → 複雑な型になるコードでも簡単に書ける
    ● もっとも汎用的な正しい型を当てはめる手法
    → 失敗しないし信頼できる(ように作る必要がある)

    View Slide

  16. 16 / 42
    1.3 型推論の短所
    ● コンパイル時間が長くなる
    ● 言語の型システムの機能が強すぎると無理
    ● 動的型付けと見た目は似てるが,動的型付き言語に
    あとから追加するのは大変難しい!

    View Slide

  17. 17 / 42
    1.3 型推論の短所
    ● コンパイル時間が長くなる
    (そのぶん動作は高速だしバグも減らせるけど)
    ● 言語の型システムの機能が強すぎると無理
    (理論的限界.一部だけ書かせるとできたりする)
    ● 動的型付けと見た目は似てるが,動的型付き言語に
    あとから追加するのは大変難しい!
    (そもそもベースが静的型付けなので……)

    View Slide

  18. 18 / 42
    2 型推論の仕組み
    ● 文脈(=変数・関数名とその型の辞書)と
    推論規則(=制約を生成するルール)を用意する

    View Slide

  19. 19 / 42
    2 型推論の仕組み
    ● 文脈(=変数・関数名とその型の辞書)と
    推論規則(=制約を生成するルール)を用意する
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する

    View Slide

  20. 20 / 42
    2 型推論の仕組み
    ● 文脈(=変数・関数名とその型の辞書)と
    推論規則(=制約を生成するルール)を用意する
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    ● 得られた制約列を単一化して,文脈に追加した
    型変数を消す(≒型の連立方程式の解を求める)

    View Slide

  21. 21 / 42
    2 型推論の仕組み
    ● 文脈(=変数・関数名とその型の辞書)と
    推論規則(=制約を生成するルール)を用意する
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    ● 得られた制約列を単一化して,文脈に追加した
    型変数を消す(≒型の連立方程式の解を求める)
    ● 必要な結果を文脈に残して次のコードに進む

    View Slide

  22. 22 / 42
    2.1 実際にやってみよう
    ● 文脈(=変数・関数名とその型の辞書)と
    推論規則(=制約を生成するルール)を用意する
    – 文脈:

    + は int 型 2 つを取って int 型を返す
    ( +: int → int → int )
    – 推論規則:
    ● 整数リテラル 0,1,2... は int 型
    ● 文脈に関数 f: a → b, 値 x: a があるとき
    関数適用 f x は b 型
    ● etc...

    View Slide

  23. 23 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    文脈
    + : int → int → int
    ※ 未知の関数・変数に対して,他と重複
    しないように型変数を生成し,文脈に追加する

    View Slide

  24. 24 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    文脈
    + : int → int → int,
    add_two : a → b
    ※ 未知の関数・変数に対して,他と重複
    しないように型変数を生成し,文脈に追加する

    View Slide

  25. 25 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    文脈
    + : int → int → int,
    add_two : a → b, x : c
    ※ 未知の関数・変数に対して,他と重複
    しないように型変数を生成し,文脈に追加する

    View Slide

  26. 26 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    a = c
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  27. 27 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    a = c, c = int
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  28. 28 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    a = c, c = int, int = int
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  29. 29 / 42
    2.1 実際にやってみよう
    ● コード中の未知の型変数を文脈に追加し,推論規則
    を用いて型の等値制約(≒型の等式)を生成する
    let-function add_two x = + x 2
    制約
    a = c, c = int, int = int, b = int
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  30. 30 / 42
    2.1 実際にやってみよう
    ● 得られた制約列を単一化して,文脈に追加した
    型変数を消す(≒型の連立方程式の解を求める)
    let-function add_two x = + x 2
    制約
    a = c, c = int, int = int, b = int
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  31. 31 / 42
    2.1 実際にやってみよう
    ● 得られた制約列を単一化して,文脈に追加した
    型変数を消す(≒型の連立方程式の解を求める)
    let-function add_two x = + x 2
    制約
    a = int, b = int, c = int
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  32. 32 / 42
    2.1 実際にやってみよう
    ● 得られた制約列を単一化して,文脈に追加した
    型変数を消す(≒型の連立方程式の解を求める)
    let-function add_two x = + x 2
    制約
    a = int, b = int, c = int
    文脈
    + : int → int → int,
    add_two : a → b, x : c

    View Slide

  33. 33 / 42
    2.1 実際にやってみよう
    ● 得られた制約列を単一化して,文脈に追加した
    型変数を消す(≒型の連立方程式の解を求める)
    let-function add_two x = + x 2
    制約
    文脈
    + : int → int → int,
    add_two : int → int, x : int

    View Slide

  34. 34 / 42
    2.1 実際にやってみよう
    ● 必要な結果を文脈に残して次のコードに進む
    ( 実装上は,スコープの中に入る前に文脈のバックアップを取り,
    結果のうちスコープの外に出るものだけを外側の文脈に追加する )
    制約
    文脈
    + : int → int → int,
    add_two : int → int, x : int
    ↓ ローカル変数(引数)

    View Slide

  35. 35 / 42
    2.1 実際にやってみよう
    ● 必要な結果を文脈に残して次のコードに進む
    ( 実装上は,スコープの中に入る前に文脈のバックアップを取り,
    結果のうちスコープの外に出るものだけを外側の文脈に追加する )
    制約
    文脈
    + : int → int → int,
    add_two : int → int

    View Slide

  36. 36 / 42
    2.2 Hindley-Milner 型推論
    ● 例えば
    は関数 f がどんな型であっても使えるはず
    ● このような関数に対して自動的に全称型を付ける(=
    ジェネリック型にする)ように設計された アルゴリ
    ズムが Hindley-Milner 型推論
    ● 中身は先ほど説明した仕組みとほぼ同じで,全称型付
    きの関数を文脈に記録する際に工夫をする
    let-function apply_twice f x = f (f x)

    View Slide

  37. 37 / 42
    2.2 Hindley-Milner 型推論
    ● Hindley-Milner を使うと,先述の例には
    という型をつけることができる
    ● Hindley-Milner の歴史は古く,だいたい 1970 年代ま
    で遡ることができる
    ● まともな型推論を積んでいる現代の言語は,ほぼ 例外
    なく Hindley-Milner かその拡張を使っている
    let-function apply_twice
    (f : T → T) (x : T) : T = f (f x)

    View Slide

  38. 38 / 42
    2.3 制約単一化型推論の限界
    ● 型の等値制約を単一化するタイプの型推論アルゴリズ
    ムは,関数・演算子のオーバーロードに対応できない
    – 解が複数存在する(が全称型にならない)ので
    「一番汎用的な型」がそもそも存在しない
    – ユーザが自作型に演算子を定義できるような場合,
    解がいくつあるのかすら分からない!
    – Hindley-Milner にオーバーロード解決を加えると
    決定不能になる(=止まらないかもしれない)

    View Slide

  39. 39 / 42
    2.3 制約単一化型推論の限界
    ● ほぼ同じ理由で,オブジェクト指向プログラミングで
    よく使われる機能への対応が難しい
    – 同じ名前のメンバやメソッドを持つ型がたくさん存
    在しうるので,それらの使い方から解が定まらない
    – 継承などの機能で部分型が導入されると,推論結果
    の汎用性に部分型関係が絡んできて難しい
    – 型の解がいくつあるのか分からなくなるような機能
    はだいたいヤバイ

    View Slide

  40. 40 / 42
    2.4 Further Reading
    ● LT の枠に収めるために端折ったり誤魔化したりした
    所が結構ある…… 特に型推論の限界はもっと色々ある
    ● 興味があって詳しく知りたい・実装してみたい方は
    B. C. Pierce 「型システム入門」を読んでみてね↓
    ● prog-lang-sys-ja.slack.com の #theory
    チャンネルに来てもらえれば,込み入った
    質問にも随時対応できますので是非〜

    View Slide

  41. 41 / 42
    Thank You!
    ● 分かりやすく説明できてたら嬉しいです
    ● 分かっちゃうと怖くない.怖くなくない?
    ● 型推論で幸せになりたいなら
    F# っていう言語がおすすめです

    View Slide

  42. 42 / 42
    質問タイム(?)

    View Slide