I have defined a nested inductive data type and have defined a custom inductive principle for it. However, automated tactics from a library I'm using (specifically, DBLib for de Bruijn indices) expects induction is on the usual inductive principle. Since I never intend to use the originally-generated inductive principle, is there any way to either replace the automatically-generated principle? Or, if not, is there a way to temporarily turn off this automatic generation?
You can do it using Elimination Schemes option. For instance,
Unset Elimination Schemes.
Inductive nat_tree : Set :=
| NNode' : nat -> list nat_tree -> nat_tree.
Set Elimination Schemes.
In addition, if you had a simpler (non-recursive) inductive type, you could have used the Variant keyword to make Coq not generate the induction principles:
Variant foo : Type := Foo.
Related
Isabelle bases its kernel proof power in resolution coupled with higher-order unification.
How are theorems proven by Coq's kernel?
The question arises from reading Paulson's "The foundation of a generic theorem prover":
Propositions-as-types could consume excessive space; and what would take the place of Huet's unification procedure for higher-order logic?
There are two kinds of technology in most provers: the "proving" part (responsible for building a proof, since it is often too tedious for the user) and the "checking" part (responsible for verifying that a proof is well-formed and matches a given theorem statement). In both Isabelle and Coq, the kernel is only responsible for the "checking" part.
In the case of Coq, the propositions-as-types paradigm is indeed used for checking proofs. In other words, a proof is a lambda-term of the Calculus of Inductive Constructions (CIC) whose type is compared to the theorem statement seen as a type.
How are theorems proven by Coq's kernel?
As explained above, theorems are not proven by Coq's kernel, only checked.
That check is done as usual with type checking: If the term is an application, check (recursively) that the arguments has the right type, and that the function return type matches the type. For example, to prove that a + f(b) has type nat, you must check that plus has type nat -> nat -> nat, that f has type A -> nat, that a has type nat and b has type A.
The proof has to be constructed by the user. The proof itself is a lambda term. The theorem proposition is the type of the lambda term.
Because it may be difficult to create the right lambda term directly, Coq does not force the user to write the whole term in one go. One can instead leave "holes" in the term to be filled in later, either by hand or with tactics. Tactics are small programs that try to fill in a piece of the proof (which may or may not be the right piece...).
Once the entire lambda term has been constructed, the proof is checked by Coq by checking that the lambda term really has the type of the proposition that one wishes to prove.
How can I get Coq to let me prove syntactic type inequality?
Negating univalence
I've read the answer to this question, which suggests that if you assume univalence, then the only way to prove type inequality is through cardinality arguments.
My understanding is - if Coq's logic is consistent with univalence, it should also be consistent with the negation of univalence. While I get that the negation of univalence would really be that some isomorphic types are non-equal, I believe it should be possible to express that no isomorphic types (that aren't identical) are equal.
Inequality for type constructors
In effect, I would like Coq to treat types and type constructors as inductive definitions, and do a typical inversion-style argument to say that my two very clearly different types are not equal.
Can it be done? This would need to be:
Useable for concrete types i.e. no type variables, and so
Not necessarily decidable
That strikes me as being weak enough to be consistent.
Context
I have a polymorphic judgement (effectively an inductive type with parameters forall X : Type, x -> Prop) for which the choice of X is decided by the constructors of the judgement.
I want to prove that, for all judgements for a certain choice of X (say X = nat) some property holds, but if I try to use inversion, some constructors give me hypotheses like nat = string (for example). These type equality hypotheses appear even for types with the same cardinality, so I can't (and don't want to) make cardinality arguments to produce a contradiction.
The unthinkable...
Should I produce an Inductive closed-world encoding of the types I care about, and let that be the polymorphic variable of the above judgement?
If you want to use type inequality, I think that the best you can do is to assume axioms for every pair of types you care about:
Axiom nat_not_string : nat <> string.
Axiom nat_not_pair : forall A B, nat <> A * B.
(* ... *)
In Coq, there is no first-class way of talking about the name of an inductively defined type, so there shouldn't be a way of stating this family of axioms with a single assumption. Naturally, you might be able to write a Coq plugin in OCaml to generate those axioms automatically every time an inductive type is defined. But the number of axioms you need grows quadratically in the number of types, so I think would quickly get out of hand.
Your "unthinkable" approach is probably the most convenient in this case, actually.
(Nit: "if Coq's logic is consistent with univalence, it should also be consistent with the negation of univalence". Yes, but only because Coq cannot prove univalence.)
I have a module and I need to specialize one of its argument. I want to use natural numbers instead of arbitrary UsualDecidableTypeFull. How can I obtain such behaviour in Coq?
I defined some module:
Module PRO2PRE_mod
(SetVars FuncSymb PredSymb PropSymb: UsualDecidableTypeFull).
(* ... *)
End PRO2PRE_mod.
Then I specialized the last of the arguments PropSymb.
Require Import Arith.PeanoNat.
Module m2 : UsualDecidableTypeFull.
Definition t:=nat.
Definition eq := #eq nat.
Definition eq_refl:=#eq_refl nat.
Definition eq_sym:=#eq_sym nat.
Definition eq_trans:=#eq_trans nat.
Definition eq_equiv:Equivalence eq := Nat.eq_equiv.
Definition eq_dec := Nat.eq_dec.
Definition eqb:=Nat.eqb.
Definition eqb_eq:=Nat.eqb_eq.
End m2.
This module needs specialization of PropVars:
Module SWAP_mod
(SetVars FuncSymb PredSymb : UsualDecidableTypeFull).
Module PRE := PRO2PRE_mod SetVars FuncSymb PredSymb m2.
Import PRE.
Theorem test : m2.t.
try exact 0. (* ERROR HERE! *)
Abort.
End SWAP_mod.
How to use theorems about natural numbers inside the last module? (I think I don't understand something about using modules... Maybe we need somehow to coerce the type 'm2.t' to the type 'nat'?)
Indeed, the use of : UsualDecidableTypeFull in the definition of m2 hides completely the implementation details of m2. From the outside, m2.t is an unknown type.
Sometimes, this is exactly what you want. For example, you may want to abstract away a type defined in a module so that the users cannot manipulate values of this type without using the functions that you gave to them in the module. You can thus ensure that they will not break some invariants.
However, in your case, you need to remember that m2.t is actually nat, you have at least these two options:
Make the interface transparent with Module m2 <: UsualDecidableTypeFull. When using this, Coq just verifies that the definition of the module complies with the signature, but does not hide the content of the module.
If you still want to hide part of the module, you can also use
Module m2 : UsualDecidableTypeFull with Definition t := nat.
In this case, from the outside, m2.t is known to be nat, but the other fields of m are masked. For instance, the body of m2.eqb is hidden.
I'm still puzzled what the sort Set means in Coq. When do I use Set and when do I use Type?
In Hott a Set is defined as a type, where identity proofs are unique.
But I think in Coq it has a different interpretation.
Set means rather different things in Coq and HoTT.
In Coq, every object has a type, including types themselves. Types of types are usually referred to as sorts, kinds or universes. In Coq, the (computationally relevant) universes are Set, and Type_i, where i ranges over natural numbers (0, 1, 2, 3, ...). We have the following inclusions:
Set <= Type_0 <= Type_1 <= Type_2 <= ...
These universes are typed as follows:
Set : Type_i for any i
Type_i : Type_j for any i < j
Like in Hott, this stratification is needed to ensure logical consistency. As Antal pointed out, Set behaves mostly like the smallest Type, with one exception: it can be made impredicative when you invoke coqtop with the -impredicative-set option. Concretely, this means that forall X : Set, A is of type Set whenever A is. In contrast, forall X : Type_i, A is of type Type_(i + 1), even when A has type Type_i.
The reason for this difference is that, due to logical paradoxes, only the lowest level of such a hierarchy can be made impredicative. You may then wonder then why Set is not made impredicative by default. This is because an impredicative Set is inconsistent with a strong form of the axiom of the excluded middle:
forall P : Prop, {P} + {~ P}.
What this axiom allows you to do is to write functions that can decide arbitrary propositions. Note that the {P} + {~ P} type lives in Set, and not Prop. The usual form of the excluded middle, forall P : Prop, P \/ ~ P, cannot be used in the same way, because things that live in Prop cannot be used in a computationally relevant way.
In addition to Arthur's answer:
From the fact that Set is located at the bottom of the hierarchy,
it follows that Set is the type of the “small” datatypes and function types, i.e. the ones whose values do not directly or indirectly involve types.
That means the following will fail:
Fail Inductive Ts : Set :=
| constrS : Set -> Ts.
with this error message:
Large non-propositional inductive types must be in Type.
As the message suggests, we can amend it by using Type:
Inductive Tt : Type :=
| constrT : Set -> Tt.
Reference:
The Essence of Coq as a Formal System by B. Jacobs (2013), pdf.
I have an inductive definition which—after evaluating—prints the warning "Ignoring recursive call". It seems that the definition works perfectly fine. However, I am still curious why exactly this warning is given. Below is a minimal example.
Inductive testor :=
| Constr1 : list testor -> testor
| Constr2 : testor -> testor.
I think the culprit is list testor in the first constructor. On the other hand, the warning is not given without the second constructor.
Q: Why is the warning emitted? Does it mean a restriction is imposed on the inductive definition?
I am using Coq 8.5.
The type testor is called a nested inductive type because of the occurrence of list testor. There is no restriction, you can safely use the definition, it's just the autogenerated induction principle is not very useful. This Coq-club thread deals with this issue. Here is an excerpt from Adam Chlipala's answer:
The warning is just about the heuristic attempts to generate a useful
induction principle. Nested inductive types (like your [AllList] use
here) call for some cleverness to build the right inductive case schemas.
For more details, see the "Nested Inductive Types" section in this chapter of CPDT.