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. 3 / 42 不毛な型推論バトル • C#/Java の var みたいなやつでしょ •

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

    → あいつらはクソザコ! • Python も型書かなくていいじゃん → 動的型付けと一緒にするな! • そんな最近出てきた機能知らない → 昔からあるし!
  3. 6 / 42 なぜ繰り返されるのか • 型推論とは一体なんなのか理解されていない (動的型付けとの違いがわからない) • 型推論の仕組みが知られてない (

    C#/Java の var との違いがわからない) • わからないものは怖がられがち (一般にアカデミアの人間は怖がられがち)
  4. 10 / 42 1 型推論ってそもそも何? • 主に静的型付き言語をターゲットとする • 変数・関数の型がほとんど or

    全く書かれていない コードに • もっとも汎用的な正しい型を当てはめる手法
  5. 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 もともとはこういう言語
  6. 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 プログラマが型を書かなくても
  7. 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 自動で最適な型をつけてくれる
  8. 14 / 42 1.2 型推論の特長 • 主に静的型付き言語をターゲットとする • 変数・関数の型がほとんど or

    全く書かれていない コードに • もっとも汎用的な正しい型を当てはめる手法
  9. 15 / 42 1.2 型推論の特長 • 主に静的型付き言語をターゲットとする → 厳格な型チェックによる利点はそのまま •

    変数・関数の型がほとんど or 全く書かれていない コードに → 複雑な型になるコードでも簡単に書ける • もっとも汎用的な正しい型を当てはめる手法 → 失敗しないし信頼できる(ように作る必要がある)
  10. 16 / 42 1.3 型推論の短所 • コンパイル時間が長くなる • 言語の型システムの機能が強すぎると無理 •

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

    (理論的限界.一部だけ書かせるとできたりする) • 動的型付けと見た目は似てるが,動的型付き言語に あとから追加するのは大変難しい! (そもそもベースが静的型付けなので……)
  12. 20 / 42 2 型推論の仕組み • 文脈(=変数・関数名とその型の辞書)と 推論規則(=制約を生成するルール)を用意する • コード中の未知の型変数を文脈に追加し,推論規則

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

    を用いて型の等値制約(≒型の等式)を生成する • 得られた制約列を単一化して,文脈に追加した 型変数を消す(≒型の連立方程式の解を求める) • 必要な結果を文脈に残して次のコードに進む
  14. 22 / 42 2.1 実際にやってみよう • 文脈(=変数・関数名とその型の辞書)と 推論規則(=制約を生成するルール)を用意する – 文脈:

    • + は int 型 2 つを取って int 型を返す ( +: int → int → int ) – 推論規則: • 整数リテラル 0,1,2... は int 型 • 文脈に関数 f: a → b, 値 x: a があるとき 関数適用 f x は b 型 • etc...
  15. 23 / 42 2.1 実際にやってみよう • コード中の未知の型変数を文脈に追加し,推論規則 を用いて型の等値制約(≒型の等式)を生成する let-function add_two

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

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

    x = + x 2 制約 文脈 + : int → int → int, add_two : a → b, x : c ※ 未知の関数・変数に対して,他と重複 しないように型変数を生成し,文脈に追加する
  18. 36 / 42 2.2 Hindley-Milner 型推論 • 例えば は関数 f

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

    • Hindley-Milner の歴史は古く,だいたい 1970 年代ま で遡ることができる • まともな型推論を積んでいる現代の言語は,ほぼ 例外 なく Hindley-Milner かその拡張を使っている let-function apply_twice<T> (f : T → T) (x : T) : T = f (f x)
  20. 38 / 42 2.3 制約単一化型推論の限界 • 型の等値制約を単一化するタイプの型推論アルゴリズ ムは,関数・演算子のオーバーロードに対応できない – 解が複数存在する(が全称型にならない)ので

    「一番汎用的な型」がそもそも存在しない – ユーザが自作型に演算子を定義できるような場合, 解がいくつあるのかすら分からない! – Hindley-Milner にオーバーロード解決を加えると 決定不能になる(=止まらないかもしれない)
  21. 39 / 42 2.3 制約単一化型推論の限界 • ほぼ同じ理由で,オブジェクト指向プログラミングで よく使われる機能への対応が難しい – 同じ名前のメンバやメソッドを持つ型がたくさん存

    在しうるので,それらの使い方から解が定まらない – 継承などの機能で部分型が導入されると,推論結果 の汎用性に部分型関係が絡んできて難しい – 型の解がいくつあるのか分からなくなるような機能 はだいたいヤバイ
  22. 40 / 42 2.4 Further Reading • LT の枠に収めるために端折ったり誤魔化したりした 所が結構ある……

    特に型推論の限界はもっと色々ある • 興味があって詳しく知りたい・実装してみたい方は B. C. Pierce 「型システム入門」を読んでみてね↓ • prog-lang-sys-ja.slack.com の #theory チャンネルに来てもらえれば,込み入った 質問にも随時対応できますので是非〜