Error: Illegal application (Non-functional construction) - coq

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).

Related

Pairs and projections in Coq

I took the following code from https://coq.inria.fr/library/Coq.Init.Datatypes.html:
Inductive prod (A B:Type) : Type :=
pair : A -> B -> A * B
where "x * y" := (prod x y) : type_scope.
Add Printing Let prod.
Notation "( x , y , .. , z )" := (pair .. (pair x y) .. z) : core_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.
When I load it into CoqIDE, at Definition fst... it comes up with the message The constructor pair (in type prod) expects 4 arguments.. How can I resolve this problem?
Add
Set Implicit Arguments.
to the top of the file.

Overcoming the need of having a constructor in the definition of an other constructor

Most probably I'm trying to achieve something flawed, but I'm running into a need to have a constructor in the definition of another constructor.
Silly example:
Inductive silly_type : Type :=
| constr1 : nat -> silly_type
| constr2 : forall (x : silly_type), (exists n : nat, (x = constr1 n)) -> silly_type.
There are two ways how to create elements of silly_type, either with natural number and constr1 or using constr2 and element of silly_type that was created with constr1.
The above definition of silly_type is not valid in coq, but I do not know how to overcome this in my less silly example.
Less silly example:
I'm trying to have an inductive type expr representing typed expressions.
Let's first start with an inductive type representing types:
Inductive type : Type :=
| base_type : nat -> type
| arrow_type : type -> type -> type
| iso_arrow_type : type -> type -> type.
There are some base types indexed with integers, arrow_type representing function between types and iso_arrow_type representing invertible functions between types.
Notation:
Notation "A --> B" := (arrow_type A B) (at level 30, right associativity).
Notation "A <-> B" := (iso_arrow_type A B).
Type for expressions:
Inductive expr : type -> Type :=
| var : forall (X : type) (n : nat), expr X
| eval : forall {X Y : type} (f : expr (X --> Y)) (x : expr X), expr Y
| inv : forall {X Y : type}, expr ((X <-> Y) --> (Y <-> X))
| to_fun : forall {X Y : type}, expr ((X <-> Y) --> (X --> Y))
| to_iso : forall {X Y : type} (f : expr (X --> Y)), (is_invertible f) -> expr (Y --> X).
You can create an indexed variables of any type with var, evaluate a function with eval, invert an invertible function with inv, cast an invertible function to the actual function with to_fun such that you can evaluate it with eval.
The problem is with the last constructor to_iso. Sometimes, I will know that a function(element of X --> Y) is actually invertible and I want some mechanism to cast it to the type X <-> Y.
However, to define is_invertible I think that I need to use eval. This leads me to the problem that the constructor eval needs to be in the definition of the constructor to_iso.
To define is_invertible, we first need to define a notion of equality of expr:
Inductive ExprEq : forall (X : type), X -> X -> Prop :=
| expr_eq_refl : forall {X : type}, forall (x : X), ExprEq X x x
| eq_on_values : forall {X Y : type}, forall (f g : (X --> Y)), (forall (x : X), f[x] == g[x]) -> f == g
where
"x == y" := (ExprEq _ x y) and "f [ x ]" := (eval f x) and "x =/= y" := (not (ExprEq _ x y)).
Thus, we have standard reflexivity x == x and equality of functions f==g can be decided by equality on all elements f[x]==g[x].
Now, we are ready to define is_invertible:
Definition is_invertible {X Y : type} (f : X --> Y) : Prop := exists g : Y --> X, (forall x, g[f[x]] == x) /\ (forall y, f[g[y]] == y).
This definition of is_invertible is problematic, it is using eval(f[x] := (eval f x)). Furthermore, the problem is a bit more complicated. We need to define the type ExprEq that already uses eval to define its constructors.
Constrain: keep expr decidable
What I really want to preserve is that the equality(=) of expr is decidable, i.e. being able to prove
Lemma eq_expr_dec {X : type} (x y : type) : {x=y} + {x<>y}.
I really do not care about decidability of the defined equality ==, but decidability of = is important for me.
You can use dependent types to index your constructors. For example
Inductive silly_type : nat -> Type :=
| constr1 : nat -> silly_type 0
| constr2 : silly_type 0 -> silly_type 1.
So you can only use values produced by constr1 in constr2. This approach should work in general to distinguish values created with different constructors.

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: The reference fst was not found in the current environment

I am writing a small program so that I can work some proofs of deMorgans laws using the type introduction/elimination rules from the HoTT book (et. al.). My model/example code is all here, https://mdnahas.github.io/doc/Reading_HoTT_in_Coq.pdf. 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.
Notation "x , y" := (pair _ _ x y) (at level 10).
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.
Inductive sum (A B : Type ) : Type :=
| inl : A -> sum A B
| inr : B -> sum A B.
Arguments inl {A B} _ , [A] B _.
Arguments inr {A B} _ , A [B].
Notation "x + y" := (sum x y) : type_scope.
Inductive Empty_set:Set :=.
Inductive unit:Set := tt:unit.
Definition Empty := Empty_set.
Definition Unit := unit.
Definition not (A:Type) : Type := A -> Empty.
Notation "~ x" := (not x) : type_scope.
Variables X:Type.
Variables Y:Type.
Goal (X * Y) -> (not X + not Y).
intro h. fst h.
Now I don't really know what the problem is. I've examples of people using definitions, but they always involve "Compute" commands, and I want to apply the rule fst to h to get x:X, so they are not helpful.
I tried "apply fst." which got me
Error: Cannot infer the implicit parameter B of fst whose type is
"Type" in environment:
h : A * B
In a proof context, Coq expects to get tactics to execute, not expressions to evaluate. Since fst is not defined as a tactic, it will give Error: The reference fst was not found in the current environment.
One possible tactic to execute along the lines of what you seem to be trying to do is set:
set (x := fst h).
I want to apply the rule fst to h to get x:X
I believe you can do
apply fst in h.
If you just write apply fst, Coq will apply the fst rule to the goal, rather than to h. If you write fst h, as Daniel says in his answer, Coq will attempt to run the fst tactic, which does not exist. In addition to Daniel's set solution, which will change the goal if fst h appears in it (and this may or may not be what you want), the following also work:
pose (fst h) as x. (* adds x := fst h to the context *)
pose proof (fst h) as x. (* adds opaque x : X to the context, justified by the term fst h *)
destruct h as [x y]. (* adds x : X and y : Y to the context, and replaces h with pair x y everywhere *)

Relationship between existential and universal quantifier in an inductive Coq definition

Suppose I want an inductive definiton of a substring (with string being just a synonym for list).
Inductive substring {A : Set} (w : string A) :
(string A) -> Prop :=
| SS_substr : forall x y z : string A,
x ++ y ++ z = w ->
substring w y.
Here I can for example prove the following:
Theorem test : substring [3;4;1] [4].
Proof.
eapply SS_substr.
cbn.
instantiate (1:=[1]).
instantiate (1:=[3]).
reflexivity.
Qed.
However, the proof is "existential" rather than "universal", in spite of the fact that the inductive definition states forall x y z and only then constrains their shapes. This seems somewhat unintuitive to me. What gives?
Also, is it possible to make an inductive definition using exists x : string A, exists y : string A, exists z : string, x ++ y ++ z = w -> substring w y?
One important thing to note is that exists is not a built-in functionality of Coq (contrary to forall). Actually, exists itself is a notation, but behind there is an inductive type named ex. The notation and the inductive type are defined in the Coq standard library. Here is the definition of ex:
Inductive ex (A:Type) (P:A -> Prop) : Prop :=
ex_intro : forall x:A, P x -> ex (A:=A) P.
It is defined using one constructor and a universal quantification, like your substring type, so it is not surprising that your susbtring type seems to be "existential" at some point.
Of course, you can define your type using exists, and you do not even need Inductive.
Definition substring' {A : Set} (w y : string A) : Prop :=
exists x z, x ++ y ++ z = w.