"Non strictly positive occurrence of ..." - coq

I try to define the following type
Inductive t : Type -> Type :=
| I : t nat
| F : forall A, (t nat -> t A) -> t A.
and I get the following error:
Non strictly positive occurrence of "t" in "forall A : Type, (t nat -> t A) -> t A".
What does this error mean?
Is there a way to "fix" the definition to make it valid?
Where can I learn more about this?
Thanks!

You can look up common error messages in the Coq reference manual: https://coq.inria.fr/distrib/current/refman/language/gallina-specification-language.html?highlight=positive#coq:exn.non-strictly-positive-occurrence-of-ident-in-type
Essentially, if a constructor contains functions (such as t nat -> t A), they cannot mention the inductive type being defined as part of an argument (t nat).
vvvvvvvvvvvvvv argument
F : ... (t nat -> t A) -> t A
^ OK ("positive occurence")
^ Not OK ("negative occurence")
This section in Certified Programming with Dependent Types (CPDT) explains the problem with a simplified example: http://adam.chlipala.net/cpdt/html/Cpdt.InductiveTypes.html#lab30
If you could define the type
Inductive term : Set :=
| App : term -> term -> term
| Abs : (term -> term) -> term.
then you could define the function
Definition uhoh (t : term) : term :=
match t with
| Abs f => f t
| _ => t
end.
and uhoh (Abs uhoh) would diverge.

Related

Specifying polarity in a module type

The following inductive definition of U is accepted by Coq because it can see that the occurrences of U in M.T U -> U are strictly positive.
Module M.
Definition T (A : Type) : Type := unit -> A.
End M.
Module N.
Inductive U : Type :=
| c : M.T U -> U.
End N.
On the other hand, the following inductive definition of U is not accepted by Coq because, depending on the definition of M.T, it might have non-strictly positive occurrences.
Module Type S.
Parameter T : Type -> Type.
End S.
Module N (M : S).
Fail Inductive U : Type :=
| c : M.T U -> U.
End N.
How can I specify in the signature S that the parameter of T should only have strictly negative occurrences? Thus preventing any non-strictly positive occurrences of U in its definition.
This U type can be seen as the least fixed point of M.T. Another common encoding is
Definition Mu (T : Type -> Type) := forall A, (T A -> A) -> A.
Definition U := Mu M.T.
Provided that T is a functor (which strict positivity would imply, maybe?):
Parameter map : forall A B, (A -> B) -> T A -> T B. (* in module M *)
we have a constructor and destructor:
Definition c : M.T U -> U := fun x A f =>
f (M.map _ _ (fun y => y _ f) x).
Definition d : U -> M.T U := fun y => y _ (fun x => M.map _ _ c x).
Showing they are inverses requires parametricity, so there is no direct way to prove it. If you don't want to axiomatize it, you can probably enrich T and U to carry evidence of parametricity.
Essentially, the requirement above that T be a functor is a semantic replacement/approximation of the strict positivity condition, which is syntactic.
It is also possible to switch off positivity checking with this new plugin:
https://github.com/SimonBoulier/TypingFlags

Would it be inconsistent to relax Coq's strict positivity checker to not look at type indices of the inductive type being defined?

Writing
Inductive Foo : Type -> Type :=
| foo : Foo Bar
with
Bar := .
gives
Error: Non strictly positive occurrence of "Bar" in "Foo Bar".
I know the standard example of why strict positivity is necessary; if I have
Inductive Fix :=
| fFix : (Fix -> Fix) -> Fix.
with an eliminator
Fix_rect : forall (P : Fix -> Type) (v : forall f, (forall x, P (f x)) -> P (fFix f)) (f : Fix), P f
then I can prove absurdity with
Fix_rect (fun _ => False) (fun f H => H (fFix id)) (fFix id) : False
(Aside: Does anything go wrong if instead the eliminator is
Fix_rect : forall (P : Fix -> Type) (v : forall f, (forall x, P x -> P (f x)) -> P (fFix f)) (f : Fix), P f
?)
However, I don't see a way to make use of occurrences that appear only in indices. Is there a way to derive a similar contradiction if non-strictly-positive occurrences are permitted in type indices?
This doesn't seem to be a positivity issue, contrary to the error message. Rather, since you have mutual indexing, this is an inductive-inductive type (a weird "large" one at that), which Coq doesn't support.
You could try defining non-indexed types, and separate recursively defined "well-formedness" relations which encode correct indexing. E. g.
Inductive PreFoo : Type :=
| foo : PreFoo.
Inductive Bar : Type :=.
Fixpoint FooWf (f : PreFoo) (t : Type) : Prop :=
match f with
| foo => (t = Bar)
end.
Definition Foo (t : Type) := sig (fun f => FooWf f t).
This is analogous to how you might have indexed intrinsic syntaxes for type theories or extrinsic presyntaxes with separate typing relations.

Error: Illegal application (Non-functional construction)

I'm trying to work some proofs of the various deMorgans laws using the type constructors/eliminators from the HoTT book. I had hopped to pick through https://mdnahas.github.io/doc/Reading_HoTT_in_Coq.pdf for relevant stuff and dump it all into a .v text file. I need Elimination/Introduction rules for product, co-product and a way to set up negation. So far I have,
Definition idmap {A:Type} (x:A) : A := x.
Inductive prod {A B:Type} : Type := pair : A -> B -> #prod A B.
Notation "x * y" := (prod x y) : type_scope.
Section projections.
Context {A : Type} {B : Type}.
Definition fst (p: A * B ) :=
match p with
| (x , y) => x
end.
Definition snd (p:A * B ) :=
match p with
| (x , y) => y
end.
End projections.
The Error on "Definition fst (p: A * B ) :=" is
Error: Illegal application (Non-functional construction):
The expression "prod" of type "Type"
cannot be applied to the term
"A" : "Type"
I tried searching through the error list on the Coq site but didn't find anything.
There are two issues with your code:
prod's two Type arguments are declared implicit
As a consequence, the notation "x * y" corresponds to prod {_} {_} x y which will always lead to ill-typed terms: prod {_} {_} is a Type and as such it does not make sense to apply something to it.
The fix is to turn these two implicit arguments into explicit ones:
Inductive prod (A B:Type) : Type := pair : A -> B -> #prod A B.
The notation (x , y) has not been declared
Once you've fixed the definition of prod, the definition still don't typecheck because Coq does not know what you mean by the pattern (x, y). You can declare it as a new notation before your Section projections like so:
Notation "x , y" := (pair _ _ x y) (at level 10).

What's with the `of` and `&` in the Coq Inductive definition?

I just saw someone defined an Inductive type in Coq in an unfamiliar syntax, like this:
Inductive nat_tree : Type :=
| NatLeaf
| NatNode of color & nat_tree & nat & nat_tree.
The syntax I am used to look like this:
Inductive ident : sort :=
ident1 : type1
| …
| identn : typen
Can anyone explain what's the new syntax?
BTW, this is from a ssrflect tutorial. And I wonder if it's a ssr addition.
Yes, you are right: this syntax is defined by Ssreflect. Both are defined as syntactic sugar for declaring an anonymous argument: of T and & T mean (_ : T); that is, an unnamed argument of type T. Thus, the definition of nat_tree is equivalent to the one below.
Inductive nat_tree :=
| NatLeaf
| NatNode (_ : color) (_ : nat_tree) (_ : nat) (_ : nat_tree).
You could also have given names to each argument:
Inductive nat_tree :=
| NatLeaf
| NatNode (c : color) (t1 : nat_tree) (n : nat) (t2 : nat_tree).
As gallais pointed out, this makes the syntax of data-type declarations in Coq more similar to OCaml's. Note that the declaration above does not give the return type of each constructor. In standard Coq, specifying the return type is optional when all the arguments are given using this syntax, and when the type being defined is uniform. This means that we are allowed to define the list type as
Inductive list (T : Type) :=
| nil
| cons (t : T) (l : list T).
but are required to define the type of length-indexed lists as follows (because of the nat index):
Inductive vector (T : Type) : nat -> Type :=
| vnil : vector T O
| vcons (n : nat) (t : T) (v : vector T n) : vector T (S n).

How to write Definitions without arguments in Coq?

I have the following Inductive type defined in Coq.
Inductive natlist : Type :=
| nil : natlist
| cons : nat -> natlist -> natlist.
Notation "x :: l" := (cons x l) (at level 60, right associativity).
Notation "[ ]" := nil.
Notation "[ x , .. , y ]" := (cons x .. (cons y nil) ..).
The natlist is basically a list of natural numbers (similar to lists in Python). I am trying to find the union of two natlist using the definition below.
Definition union_of_lists : natlist -> natlist -> natlist
i.e
Eval simpl in (union_of_lists [1,2,3] [1,4,1])
should return [1,2,3,1,4,1]
I have the following doubts.
Since there are no arguments to this definition, how do I actually get the inputs and handle them?
What does the definition union_of_lists return exactly? Is it just a natlist?
Any help or hints are highly appreciated.
I found the answer myself :) What I did was, I wrote a separate Fixpoint function append and then assigned it to the definition of union_of_lists.
Fixpoint append(l1 l2 : natlist) : natlist :=
match l1 with
| nil => l2
| (h :: t) => h :: app t l2
end.`
and then
Definition union_of_lists : natlist -> natlist -> natlist := append.
Eval simpl in (append [1,2,3] [1,2,3]) (* returns [1,2,3,1,2,3] *)
The definition union_of_lists returns a function which takes natlist as an argument and returns another function of type natlist -> natlist (i.e function taking a natlist argument and returning a natlist).
This definition of union_of_lists resembles functions in Functional Programming which can either return a function or a value.