Prevent unintentional unfolding after application in Coq - coq

My notation has been unintentionally unfolded after application.
I don't want to call the tactic 'change' on the last line in text of the tiny example every time I am using modus ponens.
How to forbid Coq to unfold my Notation "( a '==' b )"?
Require Export Coq.Vectors.Vector.
Import VectorNotations.
Inductive Terms : Type :=
FVC : nat -> Terms.
Definition Fo:=nat.
Context (axs0 : nat -> Type).
Context (Atom : Vector.t Terms 2 -> Fo).
Notation "( a '==' b )" := (Atom [a:Terms; b:Terms]).
Notation "( A --> B )" := (A + B).
Inductive GPR (axs : nat -> Type) (ctx:list nat) : nat -> Type :=
| MP (A B: Fo) : (GPR axs ctx A)->(GPR axs ctx (A --> B))
->(GPR axs ctx B).
Definition APR := GPR axs0.
Definition p2_23_a ctx (t:Terms) : APR ctx (t == t).
apply MP with (A:=(t == t)).
change (Atom [t; t]) with ((t==t)). (* <-- I don't want to write this line. *)

Change
Notation "( a '==' b )" := (Atom [a:Terms; b:Terms]).
to
Notation "( a '==' b )" := (Atom [a; b]).
Type annotations appear in the AST, and get easily simplified away, so the notation rarely matches.

Related

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

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

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.