Library apply
apply
apply も move: と同様に証明項として関数適用を構築します。
しかし、move: とは異なり、apply に指定したものが
関数適用の(引数位置ではなく)関数位置に入ります。
これを説明するのに、
P と P -> Q が成り立っていたら Q が成り立つという三段論法の証明を使いましょう。
証明項が煩雑になるのを避けるため、Section を使って
命題 P, Q および P の証明 Hp, P -> Q の証明 Hpq を宣言します。
Variable P Q :
Prop.
Variable Hp :
P.
Variable Hpq :
P → Q.
三段論法の結論 Q を証明します。
?Goal
最初の段階では証明項は構築されていないので ?Goal と表示されます。
(Hpq ?Goal)
apply Hpq により、証明項として関数適用が構築され、
その関数位置に apply に指定した Hpq が配置されます。
引数は ?Goal となっていて、まだ構築されていません。
この証明項は (Q の証明なので) Q 型の値でなければなりませんが、
それが関数適用とすると、その関数は Q 型の値を返す関数である必要があります。
Hpq は P -> Q 型の値なので、この必要性を満たしています。
Hpq の引数は P 型の値でなければならないので、これから構築する ?Goal は P 型であり、
つまりここから証明すべき命題は P となります。
(Hpq Hp)
P を証明するのは簡単です。
P 型の値として Hp があるので、それを exact Hp として証明項とすれば終わりです。
そうすると、結局、全体の証明項は Hpq Hp となります。
modus_ponens =
fun (P Q : Prop) (Hp : P) (Hpq : P -> Q) => Hpq Hp
: forall P Q : Prop, P -> (P -> Q) -> Q
section を終ってから三段論法の証明項を Print で表示すると上のようになります。
Hpq Hp という項に、P, Q, Hp, Hpq という引数の関数抽象が外側にくくられた
証明項になっていることがわかります。