厳格な陽性


10

この参照から:厳密な陽性

厳密な陽性条件は、次のような宣言を除外します

data Bad : Set where
 bad : (Bad → Bad) → Bad
         A      B       C
 -- A is in a negative position, B and C are OK

なぜAは負ですか?また、なぜBが許可されるのですか?Cが許可される理由を理解しています。


1
なぜこれが「ネガティブ」と呼ばれるのかはわかりませんが、発生するエラーでよく知られていますA
wvxvw

その部分私はあなたが任意のものを書くことができ、したがって計算が非終了になることを理解しています。感謝
Pushpa

1
質問の本文で終了しないことについて言及することは良いことだと思います。私はあなたのコメントに基づいて私の答えを更新しました。
Anton Trunov 2016

@wvxvw必ずしもそうではありません。コンパイラが末尾再帰を実装している場合は、スタックを爆破することなく永久に実行される可能性があります。たとえば、以下のOCamlの例ではスタックが爆発しません。
Anton Trunov 16

1
@AntonTrunov確かに、それは正確なものというよりも、サイトの名前をしゃれたものでした。
wvxvw

回答:


17

ABAB

次に、帰納的データ型について説明します。

TTT

代数では、操作は有限数の引数を取ることが一般的であり、ほとんどの場合、操作はゼロ(定数)、1(単項)、または2(バイナリ)の引数を取ります。データ型のコンストラクタに対してこれを一般化すると便利です。仮定cデータ型のコンストラクタですT

  • あればc一定である我々は関数として考えることができunit -> T、または同等に(empty -> T) -> T
  • c単項である場合、それを関数T -> T、または同等(unit -> T) -> Tに考えることができます、
  • cバイナリの場合、それを関数T -> T -> T、または同等にT * T -> T、または同等(bool -> T) -> Tに考えることができます。
  • c7つの引数をとるコンストラクタが必要な(seven -> T) -> T場合sevenは、7つの要素を持つ以前に定義された型である関数と見なすことができます。
  • また、c無限に多くの引数を取るコンストラクターを持つこともできます(nat -> T) -> T。それは関数です。

これらの例は、コンストラクターの一般的な形式が

c : (A -> T) -> T

我々は呼んでどこアリティのを、私たちは考える取るコンストラクタとしてタイプの-many引数をの要素を生成します。AccATT

これは非常に重要なものです:アリティはを定義するに定義する必要があります。Tそうしないと、コンストラクターが何をすることになっているのかわかりません。誰かがコンストラクターを作ろうとした場合

broken: (T -> T) -> T

次に、「引数はいくつbroken必要か」という質問です。良い答えはありません。あなたはそれを「T多くの引数をとる」で答えようとするかもしれませんが、Tまだ定義されていないので、それはしません。ファンシーな固定小数点理論を使用して型Tと単射関数を見つけることで、問題から抜け出そうとするかもしれませんが、成功するかもしれませんが(T -> T) -> T、誘導原理も途中で破っTてしまいます。だから、そのようなことを試すのは悪い考えです。

λvλvcB

c : B * (A -> T) -> T

実際、多くのコンストラクタは、このように書き換えることができ、すべてではありませんが、我々はすなわち、私たちができるようにする必要があり、一歩を必要とAする依存B

c : (∑ (x : B), A x -> T) -> T

これは帰納型のコンストラクターの最後の形式です。それはまた、正確にはWタイプです。フォームは非常に一般的であるため、必要なコンストラクタは1つだけcです。確かに、2つある場合

d' : (∑ (x : B'), A' x -> T) -> T
d'' : (∑ (x : B''), A'' x -> T) -> T

その後、それらを1つに組み合わせることができます

d : (∑ (x : B), A x -> T) -> T

どこ

B := B' + B''
A(inl x) := A' x
A(inr x) := A'' x

ちなみに、一般的な形をカレー化すると、

c : ∏ (x : B), ((A x -> T) -> T)

これは、人々が実際に証明アシスタントに書き留めたものに近いものです。証明アシスタントを使用すると、便利な方法でコンストラクターを書き留めることができますが、これらは上記の一般的な形式(演習!)と同等です。


1
もう一度ありがとう。昼食後、Andrejはこれが私にとって消化するのが最も難しいものになるでしょう。乾杯。
Pushpa

9

の最初の出現はBad、関数の引数を表すため、つまり関数の矢印の左側にあるため、「負」と呼ばれます(Philip Wadlerによる無料の再帰型を参照)。「ネガティブポジション」という用語の起源は、反変の概念に由来すると思います(「コントラ」は反対を意味します)。

型を負の位置に定義することはできません。なぜなら、それを使用して非終了プログラムを作成できるためです。つまり、その存在下で強力な正規化が失敗します(これについては以下で詳しく説明します)。ちなみに、これが「厳密な陽性」というルールの名前の理由です。負の位置は許可されません。

Bad非終了を引き起こさずBad再帰データ型のある時点(コンストラクタの最後の矢印の)で定義されている型()を使用するため、の2番目の出現を許可します。

以下の定義は厳密な陽性の規則に違反していないことを理解することが重要です。

data Good : Set where
  good : Good → Good → Good

このルールは、コンストラクターの引数(Goodこの場合は両方)にのみ適用され、コンストラクター自体には適用されません(Adam Chlipalaの「依存型の認定プログラミング」も参照してください)。

厳格な陽性に違反する別の例:

data Strange : Set where
  strange : ((Bool → Strange) → (ℕ → Strange)) → Strange
                       ^^     ^
            this Strange is   ...this arrow
            to the left of... 

また、ネガティブポジションについてこの回答を確認することもできます。


非終了の詳細...参照先のページにはいくつかの説明が含まれています(Haskellの例とともに):

厳密に正でない宣言は、それを使用して非終了関数を記述できるため、拒否されます。上記のBadデータ型を使用してループ定義を作成する方法については、BadInHaskellを参照してください。

以下はOcamlの類似の例で、再帰を直接使用せずに(!)再帰的な動作を実装する方法を示しています。

type boxed_fun =
  | Box of (boxed_fun -> boxed_fun)

(* (!) in Ocaml the 'let' construct does not permit recursion;
   one have to use the 'let rec' construct to bring 
   the name of the function under definition into scope
*)
let nonTerminating (bf:boxed_fun) : boxed_fun =
  match bf with
    Box f -> f bf

let loop = nonTerminating (Box nonTerminating)

nonTerminating機能「アンパック」オリジナル引数の引数とりんごそれから機能。ここで重要なことは、ほとんどの型システムは関数をそれ自体に渡すことを許可しないため、f fタイプfチェッカーを満たすための型がないため、などの用語は型チェックを行わないということです。タイプシステムが導入された理由の1つは、セルフアプリケーションを無効にすることです(ここを参照)。

上で紹介したようなデータ型のラッピングを使用して、不整合が生じる前にこの障害を回避できます。

終了しない計算が論理システムに不整合をもたらすことを付け加えたいと思います。AgdaとCoqの場合、False帰納的データ型にはコンストラクターがないため、False型の証明項を構築できません。しかし終了しない計算が許可されている場合、たとえばCoqで次のように実行できます。

Fixpoint loop (n : nat) : False = loop n

次に、タイプloop 0チェックを与えることloop 0 : Falseになるので、カリーハワードの対応の下では、誤った命題を証明したことになります。

効果:帰納的定義の厳密な陽性規則は、ロジックにとって悲惨な非終了計算を防ぎます。


今私は混乱しています。特にデータ良い:良いところを設定する:良い→良い→。私たちは理解して1時間以内に戻るようにします/
Pushpa

ルールはコンストラクタ自体には適用されず、その引数にのみ適用されます。つまり、コンストラクタ定義の最上位にある矢印は関係ありません。また、別の(間接的な)違反例を追加しました。
Anton Trunov 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.