あなたの直感はbool_ind
ですが、理由について考えてみましょう。bool_ind
は、他の2つを明確にするのに役立つかもしれないという意味です。 P true
が保持している場合、
- 、
bool
EANS上のすべての述語P
について
- :私たちは、これは論理式として読み取る場合
bool_ind : forall P : bool -> Prop,
P true ->
P false ->
forall b : bool,
P b
が、私たちはあなたがたのと同じ値を得ることを知っていますそして
P false
が成り立つ場合、
- すべてのブール値
b
,
しかし、これは単に論理式ではありません、それはタイプです。具体的には、(依存する)関数型です。
- 値
P : bool -> Prop
を考えると、
- 値
Pt : P true
、 :そして、関数型として、それは(あなたが私に無名の引数と結果の名前を発明の自由を許すだろう場合)と言います
- 値
Pf : P false
、そして
- 値
b : bool
、
(もちろん、これはカリー化関数であるので、そこ散文にタイプを打破するために、他の方法がありますが、これは我々の目的のために最も明確です。)
ここで重要なのは、プログラミング言語である間にCoqを定理証明者として働かせることです(逆も同様)。Curry-Howard correspondence:型は命題であり、値はそれらの命題の証明です。たとえば、単純な関数タイプ->
は含意に対応し、従属関数タイプforall
は普遍的な定量化に対応します。 )Coqでは、φ→ψを証明するために、タイプφ
(つまり命題の証明)の値をとる関数φ -> ψ
の値を構築する必要がありますφ)を計算し、これを使用してタイプψ
(命題ψの証明)の値を構築します。
Coqでは、Set
、Type
、またはProp
のいずれであるかにかかわらず、このようにすべてのタイプについて考えることができます。 (だから、「それは真実かどうかのように(bool recのためのSetとbool_rectのTypeは命題の値として扱われているようです)」と言うとき、あなたは正しいと思います。 bool_ind
を実装してください。ファンクションのすべてのパラメータを戻り値の型とともにリストします。
Definition bool_ind' (P : bool -> Prop)
(Pt : P true)
(Pf : P false)
(b : bool)
: P b :=
これまでのところ、とても良いです。この時点で、タイプP b
の商品を返品したいと考えていますが、b
が何であるかわかりません。したがって、これらの状況ではいつものように、パターンマッチ:
match b with
ここで2つのケースがあります。まず、b
をtrue
とすることができます。この場合、タイプP true
のものを返す必要があります。幸いなことに、このような値はPt
です。
| true => Pt
false
場合も同様です:
| false => Pf
end.
注我々はbool_ind'
を実装する場合、それは非常に "proofy、" ではなく、非常に "programmy" を見ていないこと。もちろん、カリー・ハワードのおかげで、これらは同じです。しかし、非常に同じ実装は、他の2つの機能のために十分ですのでご注意:この計算の定義を見てみると
Definition bool_rec' (P : bool -> Set)
(Pt : P true)
(Pf : P false)
(b : bool)
: P b :=
match b with
| true => Pt
| false => Pf
end.
Definition bool_rect' (P : bool -> Type)
(Pt : P true)
(Pf : P false)
(b : bool)
: P b :=
match b with
| true => Pt
| false => Pf
end.
は別の事についてbool_ind
、bool_rec
をする方法、およびbool_rect
を公開します。彼らはあなたがについて話を知っておくべきことをカプセル化すべての値はbool
です。しかしどちらの方法でも、私たちはその情報をパッケージ化しています。もし私がtrue
の何かを知っていて、false
の何かを知っていれば、私はbool
のすべてについてそれを知っています。
bool_{ind,rec,rect}
関数の定義は、ブール値に関数を書き込む通常の方法よりも抽象的です。真の枝に対応する1つの引数と、偽の枝に1つの引数があります。つまり、これらの関数はちょうどif
ステートメントです。型は値に依存することができますので、私たちはどこでも種類によってb
を通す必要があり、しかし
Definition bool_simple_rec (S : Set) (St : P) (Sf : P) (b : bool) : S :=
match b with
| true => St
| false => Sf
end.
:非依存的型付けされた言語では、彼らは単純なタイプforall S : Set, S -> S -> bool -> S
を持つことができます。それが判明した場合、我々は、しかし、我々はより多くの一般的な機能を使用して伝えることができることを望んでいない:
Definition bool_simple_rec' (S : Set) : S -> S -> bool -> S :=
bool_rec (fun _ => S).
誰も私たちのP : bool -> Set
が使用bool
に持っていた言いませんでした!
タイプのこれらの関数は、いずれももっと面白いです。例えば、コックは自然数の次のような種類があります。
Inductive nat : Set := O : nat | S : nat -> nat.
をそして、我々は、対応するnat_rec
とnat_rect
とともに
nat_ind : forall P : nat -> Prop,
P O ->
(forall n' : nat, P n' -> P (S n')) ->
forall n : nat,
P n
を持っています。 (読者のための演習:これらの機能を直接実装してください)
一見、これは数学的誘導の原理に過ぎません。しかし、それはまた、nat
sに再帰関数を書く方法です。彼らは同じことです。一般的な、再帰関数でnat
上に次のようになり:
fix f n => match n with
| O => ...
| S n' => ... f n' ...
end
O
(ベースケース)は、以下の一致のアームは、単にタイプP O
の値です。 S n'
(再帰的なケース)に続くマッチは、タイプforall n' : nat, P n' -> P (S n')
の関数に渡されます。n'
は同じであり、P n'
の値は再帰呼び出しf n'
の結果です。
私はbool
よりも無限の種類に明確だと思う当時と_rec
と_ind
機能間の等価、1について考えるもう一つの方法は、それが中で起こる数学ind
uction間の等価(と同じだということ-is Prop
)および(構造)rec
ursion(これはSet
およびType
で発生します)。
これらの機能を使用しましょう。ブール値を自然数に変換するシンプルな関数を定義します。これは直接とbool_rec
の両方で行います。
Definition bool_to_nat_match (b : bool) : nat :=
match b with
| true => 1
| false => 0
end.
別の定義が
Definition bool_to_nat_rec : bool -> nat :=
bool_rec (fun _ => nat) 1 0.
されており、これら2つの関数は同じです:
Goal bool_to_nat_match = bool_to_nat_rec.
Proof. reflexivity. Qed.
(注:この関数を記述するための最も簡単な方法は、パターンマッチであり、これらは、関数はであり、構文的にはと等しいです。これは単純に同じことをするよりも強い条件です)
ここで、P : bool -> Set
はfun _ => nat
です。引数に依存しない戻り値の型を返します。私たちのPt : P true
は1
です。true
が与えられたときに計算するものです。同様に、Pf : P false
は0
です。ここに答えがあります:
Fixpoint nat_rect' (P : nat -> Type)
(base_case : P 0)
(recurse : forall n', P n' -> P (S n'))
(n : nat)
: P n :=
match n with
| O => base_case
| S n' => recurse n' (nat_rect' P base_case recurse n')
end.
これがうまくいけば、それは明らかにちょうどどのようnat_rect
は再帰パターンを抽象化し、そしてなぜそれが十分に一般的です。
非常に詳細な回答ありがとうございます。私はまだそれを理解しています。私はカリー・ハワードの対応について知らなかったし、それでもまだそれを得ていない。これらの関数を直接(たとえば否定を定義するために)どのように使用しますか? (チュートリアルの使い方は "elim"にカプセル化されているので、明示的に使われている例は見つけられません) – dspyz
bool_indの定義には次のものがあります:Pt:P true、しかしPではありませんtrue要素(例えばPt)の型の値がProp型の型を持つことができますか? Ptのタイプもプロップですか?もしそうなら、Pのポイントは何ですか? – dspyz
あなたの第一の質問が何を求めているのかよく分かりません。 *どの*関数を直接使うことができますか?あなたの2番目の質問では、Coqのすべての値には*:*、 'O:nat'、' I:True'のような型があります。しかし、Coqは依存型であるため、型はちょうど(特別な)値なので、 'nat:Set'と' True:Prop'型を持たなければなりません(型の型は、従属型言語)。また、これらの型は 'Set:Type'、' Prop:Type'型でなければなりません。だから私たちは 'Pt:P true:Prop'を' O:nat:Set'と同じように持っています。 'P'のポイントは特定の命題を選ぶことです。 –