web-dev-qa-db-ja.com

「あなたはヒンドリー - ミルナーのどの部分を理解していないのですか?」

Iswear以前は不滅の言葉が書かれたTシャツが販売されていました。


何の部分

Hindley-Milner

notわかりますか?


私の場合は、答えは…すべてです。

特に、Haskellの論文ではこのような表記法がよく見られますが、それが何を意味するのかはわかりません。私はそれがどのような数学の分野であるべきか分からない。

私はもちろんギリシャ文字のアルファベットと "∉"のような記号を認識しています(これは通常何かが集合の要素ではないことを意味します)。

その一方で、私は前に "⊢"を見たことがない( ウィキペディアはそれが "パーティション"を意味するかもしれないと主張している )。私はまた、このビンクラムの使い方に慣れていません。 (通常は分数を表しますが、が現れるはここでは当てはまりません。)

誰かが少なくともこのシンボルの海が何を意味するのか理解するために探し始めるところを私に言うことができればそれは役に立ちます。

817
  • 水平バーは、「[上記] 暗黙 [以下]」を意味します。
  • [=]に複数の式がある場合、それらをanded一緒に検討してください。 [上記]のすべてが[下]を保証するために真でなければなりません。
  • :タイプありを意味します
  • は、is inを意味します。 (同様には「中にない」ことを意味します。)
  • Γは通常、環境またはコンテキストを参照するために使用されます。この場合、識別子をそのタイプとペアにするタイプ注釈のセットと考えることができます。したがって、x : σ ∈ Γは、環境Γxのタイプがσであるという事実を含むことを意味します。
  • は、provesとして読み取るか、決定します。 Γ ⊢ x : σは、環境Γxのタイプがσであることを決定することを意味します。
  • ,含む環境への特定の追加仮定Γの方法です。
    したがって、Γ, x : τ ⊢ e : τ'は、環境Γxのタイプがτeのタイプがτ'であることを証明します。

要求どおり:演算子の優先順位、最高から最低まで:

  • λ x . e∀ α . σ、およびτ → τ'let x = e0 in e1、および関数適用用の空白など、言語固有の中置演算子とmixfix演算子。
  • :
  • および
  • ,(左結合)
  • 複数の命題を分離する空白(連想)
  • 水平バー
627
Dan Burton

この構文は、複雑に見えるかもしれませんが、実際には非常に単純です。基本的な考え方は形式的な論理に基づいています。表現全体は、上半分が仮定であり、下半分が結果であるという意味合いです。つまり、上の式が真であることを知っている場合、下の式も真であると結論付けることができます。

記号

留意すべきもう1つのことは、一部の文字には伝統的な意味があるということです。特に、Γはあなたがいる「コンテキスト」、つまり、あなたが見た他の物のタイプを表します。したがって、Γ ⊢ ...のようなものは、...内のすべての式のタイプを知っている場合、「式Γ」を意味します。

シンボルは、本質的に何かを証明できることを意味します。したがって、Γ ⊢ ...は、「コンテキストで...を証明できますΓ。これらのステートメントは型判定とも呼ばれます。

留意すべきもう1つの点は、数学では、MLやScalaと同様に、x : σxの型がσであることを意味します。 Haskellのx :: σと同じように読むことができます。

各ルールの意味

したがって、これを知っていると、最初の式が理解しやすくなります。x : σ ∈ Γ(つまり、xが何らかのコンテキストσを持っていることがわかっている場合、Γ)、Γ ⊢ x : σ(つまり、Γでは、xの型はσです)。だから本当に、これはあなたに何か面白いことを言っているわけではありません。コンテキストの使用方法を示しているだけです。

他のルールも簡単です。たとえば、[App]を使用します。このルールには2つの条件があります。e₀は、あるタイプτからあるタイプτ'への関数であり、e₁はタイプτの値です。これで、e₀e₁に適用することで、取得するタイプがわかります。うまくいけば、これは驚きではありません:)。

次のルールには、さらに新しい構文があります。特に、Γ, x : τは、Γと判断x : τで構成されるコンテキストを意味します。したがって、変数xの型がτであり、式eの型がτ'であることがわかっている場合、xを取り、eを返す関数の型もわかります。これは、関数がどの型を取り、どの型が返すかを把握した場合の対処方法を示しているだけなので、どちらも驚くべきことではありません。

次は、letステートメントの処理方法を示しています。 xの型がe₁である限り、いくつかの式τの型がσであることがわかっている場合、letσの値にローカルにバインドするxe₁の型はτになります。実際、これは、letステートメントを使用すると、基本的に新しいバインディングでコンテキストを拡張できることを示しています。これはまさにletが行うことです!

[Inst]ルールはサブタイピングを扱います。タイプσ'の値があり、それがσのサブタイプである場合(は半順序関係を表します)、その式はタイプσ

最後のルールは、型の一般化を扱います。余談ですが、自由変数とは、式の中のlet文やラムダによって導入されない変数です。この式は、そのコンテキストからの自由変数の値に依存するようになりました。ルールは、コンテキスト内の何かにnot "free"である変数αがある場合、 e : σを知っている型の式は、any value of αに対してその型を持つと言っても安全です。

ルールの使用方法

さて、あなたはシンボルを理解したので、これらのルールで何をしますか?さて、これらのルールを使用して、さまざまな値のタイプを把握できます。これを行うには、式(たとえばf x y)を見て、ステートメントに一致する結論(下部)を持つルールを見つけます。あなたの「目標」を見つけようとしているものを呼びましょう。この場合、e₀ e₁で終わるルールを確認します。これを見つけたら、このルールの境界より上のすべてを証明するルールを見つける必要があります。これらは一般にサブ式のタイプに対応しているため、本質的に式の一部を再帰しています。プルーフツリーが完成するまでこれを行うだけで、式のタイプの証明が得られます。

したがって、これらのルールはすべて、式のタイプをどのように把握するかを正確に指定することです。

これで、Prologを使用したことがあるなら、これはおなじみのはずです。つまり、本質的にはPrologインタプリタのような証明ツリーを計算していることになります。 Prologが「論理プログラミング」と呼ばれる理由があります! H-M推論アルゴリズムに最初に導入された方法は、Prologに実装することであったため、これも重要です。これは実際には驚くほど単純で、何が起こっているかを明確にします。ぜひ試してみてください。

注:この説明で間違いを犯した可能性があります。誰かが指摘してくれたらそれを気に入ってくれるでしょう。私は実際に数週間でクラスでこれをカバーするので、私はその時より自信があります:P。

319
Tikhon Jelvis

誰かが少なくともこのシンボルの海が何を意味するのか理解するために探し始めるところを私に言うことができれば

判断と導出による論理のスタイルについては、 " プログラミング言語の実用的な基礎 - "の第2章と第3章を参照してください。本全体は 現在Amazonで入手可能です。

第2章

帰納的定義

帰納的定義はプログラミング言語の研究において不可欠なツールです。この章では、帰納的定義の基本的な枠組みを開発し、それらの使用例をいくつか示します。帰納的定義は、さまざまな形式の判断または表明を導出するための規則の集合で構成されます。判断は、指定された種類の1つ以上の構文オブジェクトに関するステートメントです。規則は、判決の有効性のために必要かつ十分な条件を指定し、それゆえその意味を完全に決定する。

2.1判断

構文オブジェクトについてのjudgement、またはassertionという概念から始めます。私たちは、次のような例を含め、さまざまな形態の判断を利用します。

  • n nat - nは自然数です。
  • n = n1 + n2 - nn1n2の合計です
  • τ type - τは型です
  • eτ - 式eの型はτです
  • ev - 式eの値はv

判断は、1つ以上の構文上の目的語が相互に関連して性質を持つか立っていると述べます。性質または関係そのものを判定形式と呼び、オブジェクトがその性質を持っている、またはその関係にあるという判断は、その判断形式のインスタンスと呼ばれます。判定形式は述語とも呼ばれ、インスタンスを構成するオブジェクトはその主語です。 _ j _ aが成り立つと判断するためにa _ j _ と書きます。判決の主題を強調することが重要ではない場合(本文はここでは切り捨てられます)

70
Don Stewart

記法は 自然な控除 から来る。

記号は 回転木戸 と呼ばれます。

6つのルールはとても簡単です。

Varの規則はどちらかというと些細な規則です - もしidentifierのための型があなたの型環境に既に存在するのなら、その型を推論するためにはそのまま環境からそれを取り出すということです。

Appルールは、e0e1の2つの識別子があり、それらの型を推測できる場合は、アプリケーションの型e0 e1を推測できると述べています。 e0 :: t0 -> t1e1 :: t0(同じt0!)を知っていれば、規則は次のようになります。アプリケーションは正しく型付けされ、型はt1です。

AbsLetは、ラムダ抽象化とレットインの型を推測するための規則です。

Inst規則は、あなたがより一般的でないものでタイプを置き換えることができると言います。

48
nponeccop

Hindley-Milnerのルールをどのように理解すればよいですか?

Hindley-Milnerは、 逐次計算 (自然な推論ではない)という形式の一連の規則であり、明示的な型宣言を行わなくてもプログラムの構成から(最も一般的な)プログラムの型を推論できます。

記号と表記

まず、記号について説明しましょう

  • ????は識別子(非公式には変数名)です。
  • meansの一種です(非公式に、のインスタンス、または "is-a")。
  • ????(σ)は、変数または関数のいずれかである式です。
  • εは次の要素です
  • ???? (ガンマ)は環境です。
  • (アサーション記号)は アサート (または証明しますが、文脈的には「アサート」の方が読みやすくなります)を意味します。
  • ????⊦????????は、このように読み込まれます。 ????、a ????をアサート
  • ????は、タイプ????の実際のインスタンス(要素)です。
  • ????(τ)は型です。基本、変数(????)、汎関数????→???? '、または製品????×???? '
  • ????→???? 'は関数型で、????????'は型です。
  • ????????。????????(ラムダ)が引数を取る無名関数であることを意味します、????、そして式????を返します。
  • let????= ???? 0in???? 1は式の意味、{???? 1????が表示されている場合は必ず???? 0を代入してください。
  • は、前の要素が後者の要素のサブタイプ(非公式にサブクラス)であることを意味します。
  • ????は型変数です。
  • ????。????は型、∀(すべての場合)引数変数、????、戻り値????表現
  • free(????)は????の自由型変数の要素ではないことを意味します外部コンテキストで定義されています。 (束縛変数は代入可能です。)

それより上のものはすべて前提であり、下のものはすべて結論です( Per Martin-Löf

この後に続くのは論理ステートメントの英語の解釈であり、その後に緩やかな言い換えと説明が続きます。

変数

VAR Logic Diagram

与えられた? ????の一種です。 σ、????の要素(ガンマ)、
結論を出すアサート???は????です。

別の言い方をすれば、????で、私たちは????を知っているは?なぜですか?は?で???.

これは基本的にはトートロジーです。識別子名は変数または関数です。

機能アプリケーション

APP Logic Diagram

与えられた? ???? 0は関数型であり、???? ???? 1はa ????です。
結論を出すに関数を適用することを表明する。

規則を言い換えると、関数applicationはtype ???? 'を返すことがわかります。関数の型が????→???? 'であるためそして????型の引数を取得します。

つまり、関数が型を返すことがわかっていて、それを引数に適用すると、結果は返された型のインスタンスになります。

関数の抽象化

ABS Logic Diagram

与えられた?そして???タイプの???アサート???型です、???? '
結論を出す無名関数をアサートします。の式を返す????→???? '型です。

再度、私達が取る機能を見るとき????そして、????という式を返します。これは、????→???? '型であることがわかります。なぜですか? (a ????)はそれを主張しています????は???? 'です。

私たちが知っていれば?は?したがって式???? ???? '型の場合は、????の関数式を返す????→???? '型です。

変数宣言をしましょう

LET Logic Diagram

与えられた? ????、and ????の???? 0をアサートそして、????型の????は、????型の???? 1をアサートします。
結論を出す????型のlet ???? = ???? 0 in ???? 1をアサートします。

ゆるい???なぜなら、は、であるからであり、そして、は、である。は何ですか?これは???? 1がa ????であることを表明しています。

これは、私たちがa ????という式???? 0を持っている場合を意味します。 (変数または関数である)、そして名前、????、また????、および式????の式???? 1は、その代わりに???? 0を代入することができます。 ????それが???? 1の中に現れるところはどこでも。

インスタンス化

INST Logic Diagram

与えられた?アサート??? ???? 'タイプのそして???? ' ????のサブタイプです。
結論を出すアサート???は?

表現、 ????は親タイプです。という表現だから?サブタイプ???? '、そして???? ???? 'の親タイプです。

あるインスタンスが別の型のサブタイプである型の場合、それはそのスーパータイプのインスタンスでもあります。より一般的な型です。

一般化

GEN Logic Diagram

与えられた?アサート???は何ですか? and ????は、????の自由変数の要素ではありません。
結論を出す????をアサートし、すべての引数式を入力します。を返す表現

だから一般的に、???入力されている? ????を返すすべての引数変数(????)に対しては何ですか?そして???自由変数ではありません。

これは、包含範囲にまだ束縛されていない引数(非局所的ではない変数)に対してすべての型を受け入れるようにプログラムを一般化できることを意味します。これらの束縛変数は代用可能です。

すべてを一緒に入れて

特定の仮定(自由/未定義の変数がない、既知の環​​境など)を考えると、次のような種類があります。

  • 私たちのプログラムの基本要素(変数)
  • 関数から返される値(Function Application)
  • 機能構成(Function Abstraction)、
  • let束縛(Let変数宣言)、
  • インスタンスの親タイプ(Instantiation)
  • すべての式(汎化).

結論

これらの規則を組み合わせることで、型注釈を必要とせずに、最も一般的な型のアサートプログラムを証明できます。

40
Aaron Hall

Eについて考える2つの方法があります。 1つは「式eが型σを持つ」、もう1つが「式eと型σの順序対」です。

Γを式と型のペアのセットとして実装された式のタイプに関する知識として見てください。

回転木戸⊢は、左側の知識から、右側にあるものを推測できることを意味します。

したがって、最初の規則[Var]を読むことができます。
私たちの知識Γがe:σのペアを含んでいる場合、eからタイプσを持つことをΓから推測することができます。

2番目のルール[App]は読むことができます:
Γから我々がe_0が型τ→τ 'を持つと推論することができ、そしてΓから我々がe_1が型τを持つと推論することができるなら、Γから私たちはe_0 e_1が型τ'を持つと推論することができる。

Γ` {e:σ}の代わりにΓ、e:σと書くのが一般的です。

したがって、3番目の規則[Abs]を読むことができます。
x:τで拡張されたΓから我々が、eが型τ 'を有すると推定することができるならば、Γから、λx.eが型τ→τ'を有すると推定することができる。

4番目のルール[Let]は練習問題として残されています。 :-)

5番目のルール[Inst]は読むことができます:
Γから我々がeが型σ 'を有し、σ'がσのサブタイプであると推定できる場合、Γから我々はeが型σを有すると推定することができる。

6番目と最後の規則[Gen]を読むことができます。
Γから我々がeが型σを持ち、αがΓ内の型のいずれにおいても自由型変数ではないと推定できる場合、Γから私たちはeが型∀ασを持つと推定することができる。

16
Per Persson