契約と依存型付けとの関係


31

私は依存型とプログラミング契約に関するいくつかの記事を読んでいます。私が読んだことの大部分から、契約は動的にチェックされる制約であり、依存型は静的にチェックされるようです。

部分的に静的にチェックされる契約を持つことは可能だと私に思わせたいくつかの論文がありました:

これにより、かなりの量の重複があるようで、契約と従属タイプの分類が消え始めます。

どちらの概念にも、私が見逃しているものがありますか?それとも、これらは、同じ基本概念を表すファジーカテゴリに過ぎませんか?

回答:


26

実用レベルでは、契約はアサーションです。これらを使用すると、プログラムの個々の実行の(数量詞なしの)プロパティを確認できます。契約チェックの中心にある重要なアイデアは、非難のアイデアです。基本的に、契約違反の責任者を知りたいと思います。これは、実装(約束した値を計算しない)または呼び出し元(関数に誤った種類の値を渡した)のいずれかです。

重要な洞察は、領域理論の逆極限構築における埋め込みと投影のペアと同じ機構を使用して、責任を追跡できることです。基本的に、アサーションの操作からアサーションのペアの操作に切り替えます。アサーションの1つはプログラムコンテキストを非難し、もう1つはプログラムを非難します。次に、アサーションのペアを交換することにより、関数空間の反分散をモデル化できるため、これによりコントラクトで高次関数をラップできます。(たとえば、ニックベントンの論文「Undoing Dynamic Typing」を参照してください。)

依存型は型です。タイプは、特定のプログラムが受け入れられるかどうかをアサートするためのルールを指定します。その結果、それらの機能は不正なプログラムがそもそも存在するのを防ぐことであるため、非難の概念のようなものは含まれません。整形式のプログラムだけが文法的な発話でもあるため、非難することはありません。実用的には、これは、依存型を使用して、量指定子を使用して用語のプロパティを話すことが非常に簡単であることを意味します(たとえば、関数はすべての入力に対して機能します)。

これら2つのビューは同じではありませんが、関連しています。基本的に、ポイントは、契約では、普遍的な価値の領域から始め、契約を使用して物事を削減することです。ただし、型を使用する場合は、(必要なプロパティを持つ)値の小さなドメインを前もって指定しようとします。したがって、タイプ指向の関係ファミリ(つまり論理関係)を介して2つを接続できます。たとえば、Ahmed、Findler、Siek、Wadlerの最近の「Blame for All」、またはReynoldsの「The Meaning of Types:Intrinsic to Extrinsic Semantics」を参照してください


なぜ契約は量指定子を含まないと言うのですか?
ラドゥグリゴール

3
一般に、テストを使用して汎用的に定量化された関数のプロパティを確立することはできないため、それだけです。
ニールクリシュナ

3
数量詞が有限領域に及ぶ場合を除き、その場合、それらは大きな接続詞と選言として見ることができます。または、空想を得たい場合は、特定の種類の定量化されたステートメントを確認できます。ただし、量的範囲がMartin Escardoの検索可能なタイプ(無限の場合もあります)に及ぶ場合に限ります。
アンドレイバウアー

2
@Radu:JML&coのようなものを「プログラムロジック」と呼びます。プログラムロジックのアサーション言語は、プログラムの言語の用語に限定されません。これにより、適切な論理的解釈を持たない非終了アサーションや副作用アサーションなどを除外できます。(ただし、そのようなことは、契約のチェックに問題ない-直線性の性質を追跡するために、ステートフル、不可欠の契約を使用してESOPでPucellaとトーベの最近の作品を参照してください。)
ニールKrishnaswami

2
Tovの姓のスペルを間違えたからです。「アフィン型のステートフルコントラクト」、ccs.neu.edu / home / tov / pubs / affine
ニールクリシュナ

13

タイプとコントラクトの両方が攻撃する(かなり抽象的な)問題は、「プログラムに特定のプロパティを持たせる方法」です。ここには、より広範なクラスのプロパティを表現できることと、プログラムにプロパティがあるかどうかをチェックできることとの間に固有の緊張があります。通常、型システムは非常に特定のプロパティを保証し(プログラムが特定の方法でクラッシュすることはありません)、型チェックアルゴリズムを備えています。一方、コントラクトでは、非常に広範囲のプロパティを指定できます(たとえば、このプログラムの出力は素数です)が、チェックアルゴリズムは付属していません。

それでも、コントラクトチェックアルゴリズムがない(常に機能する)ことは、コントラクトチェックアルゴリズムがほとんどないことを意味するものではありません(実際に機能する傾向があります)。Spec#Frama-CのJessieプラグインをご覧になることをお勧めします。どちらも、「このプログラムはこの契約に従う」ことを検証条件生成を介して1次論理のステートメントとして表現し、SMTに問い合わせることで機能します。ソルバーは、証拠を見つけようとします。ソルバーが証明を見つけられない場合、プログラムが間違っているか、存在する証明を見つけることができませんでした。(これが「ほぼ」コントラクトチェックアルゴリズムである理由です。)シンボリック実行に基づくツールもあります。つまり、「このプログラムはこのコントラクトに従う」ということは、いくつかの命題として表現されます。たとえば、jStarを参照してください。

フラナガンの仕事は、両方の世界から最高のものを取り込もうとするので、タイプのようなプロパティをすばやくチェックし、残りの作業をすることができます。私はハイブリッド型にはあまり馴染みがありませんが、筆者は、以前のESC / Javaでの作業よりも少ないアノテーションを必要とするソリューションを考え出すことが彼の動機だったと言ったことを覚えています。ただし、ある意味では、ESC / Java(およびSpec#)でも型とコントラクトの間に緩やかな統合がいくつかあります。コントラクトをチェックするとき、ソルバーはその情報を確認できるように型チェックが成功したと通知されます。


7

契約は静的に確認できます。Dana XuのESC / Haskellに関する古い研究を見ると、彼女はコンパイル時に完全なコントラクトチェックを実装することができ、算術は定理証明に頼っていました。正しく覚えていれば、終了は単純な深さ制限によって解決されます。


6

コントラクトとタイプの両方を使用すると、関数のHoareスタイル(事前/事後条件)仕様を表すことができます。両方とも、コンパイル時に静的にチェックすることも、実行時に動的にチェックすることもできます。

依存型を使用すると、コントラクトプログラマーが期待する種類のプロパティである、タイプシステムの非常に広範なプロパティをエンコードできます。これは、タイプの値に依存する可能性があるためです。依存型は静的にチェックされる傾向がありますが、引用した論文では別のアプローチを検討していると思います。

最終的に、ほとんど違いはありません。依存型は仕様を表現できるロジックであるのに対し、コントラクトは仕様を表現するプログラミング手法であると思います。


Hoareスタイルのアノテーションは静的にチェックできると言うのは少し誤解を招くかもしれません。ロジックが通常どおりFOである場合、問題は確かに決定できません。しかし、はい、私はあなたが人が多くの状況で試して成功することさえできることを意味したことを知っています。
ラドゥグリゴール

1
私は、プルーフを生成することは決定できないかもしれないが、プルーフをチェックするべきであるという印象を受けていました。多くの依存型言語は、定理型の居住性の証明値を提供するためにユーザーに依存しています。
ジェイソンライヒ

あなたが正しいです。しかし、私は自動化された世界に住んでおり、ユーザーは通常、証拠を求められません
ラドゥグリゴール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.