Reputation: 15492
Coq seems to assume ex falso quodlibet / the principle of explosion (PEP).
The induction principle generated from a data type definition with no constructors is PEP:
False_ind =
fun (P : Prop) (f : False) => match f return P with
end
: forall P : Prop, False -> P
This principal seems to be necessary for proving things like disjunctive syllogism:
Lemma disj_syll : forall (A B: Prop), A \/ B -> (not B) -> A.
Proof.
intros.
destruct H.
- (* prove A from A *) assumption.
- (* prove A from B and ~B *) contradiction.
Qed.
So that's what PEP buys us in terms of proving. But what about programming?
I can't figure out what it would mean to drop PEP and am really confused by the program extraction output.
As far as I can tell:
Scheme:
(load "macros_extr.scm")
(define __ (lambda (_) __))
(define disj_syll __)
Haskell:
module Disj_syll where
import qualified Prelude
__ :: any
__ = Prelude.error "Logical or arity value used"
disj_syll :: ()
disj_syll = __
What is going on?
I'm asking this question because the connection between proofs and programs (Propositions-as-Types / Curry-Howard Isomorphism) seems well-understood for the logical connectives generally, but PEP is an axiom in Heyting and Kolmogorov's formalizations of intuitionistic logic (Kolmogorov and Brouwer on constructive implication and the Ex Falso rule, Van Dalen 2004). It's hard for me to see what the computational content of such an axiom is, especially when it says "Given that you have constructed the unconstructable, you now get (for free!) a construction of anything you choose to imagine)." I don't know how to write a program to do such a thing, and Coq's program extraction doesn't seem to have a consistent perspective on the matter either.
Upvotes: 0
Views: 385
Reputation: 15404
Would giving up on 'ex falso' change anything w.r.t. dependently-typed programming in Coq?
Yes, it would. Let us consider the hello-world of dependently typed programming, namely length-indexed lists (a.k.a. vectors). It is defined in the standard library, but let me give it here for context.
Inductive vec (A : Type) : nat -> Type :=
| vnil : vec A 0
| vcons n : A -> vec A n -> vec A (S n).
Now, we might want to provide the analogue of the head
function on regular (non-indexed) lists. There is many approaches to deal with the case of the empty list as the input of head
for lists. But for vectors it is especially easy to ask for non-empty input: we put this restriction in the type of the input v : vec A (S n)
, where S n
ensures that the length of the input vector is not zero.
Here is a stub for this function:
Fixpoint head {A n} (v : vec A (S n)) : A :=
match v with
| vnil _ => _
| vcons _ n hd tl => hd
end.
But what do we return in case of the empty input? Coq won't let us simply omit vnil
constructor in the pattern-matching expression. Here we can use the principle of explosion to solve the issue. Here is one possible way to fill in the blank above:
Fixpoint head {A n} (v : vec A (S n)) : A :=
match v in vec _ len
return (len = S n -> A)
with
| vnil _ => fun contra => False_rect _ (O_S _ contra)
| vcons _ n hd tl => fun _ => hd
end eq_refl.
This solution uses the so-called "convoy pattern" which is described in several Stackoverflow answers and in the CPDT book by Adam Chlipala. It also uses the standard O_S
lemma (of type forall n : nat, 0 <> S n
), so (O_S _ contra)
has type type False
.
Upvotes: 3
Reputation: 291
The standard computational interpretation for PEP is just the program crashing, since it requires a logically impossible premise. In the Scheme code, crashing is represented by the program looping, and in Haskell, this is a toplevel exception. But in both cases we know this is dead code and should never be reached, except if Coq is inconsistent itself.
Note that Coq is consistent with alternative computational interpretations of PEP, though. One can apply a variant of Friedman's A-translation to Coq to replace crashing by raising recoverable exceptions. See the Exceptional model for more details.
Upvotes: 3