I'd like to create notations for several kinds of judgements, for example for a typing and subtyping relation:
Reserved Notation "Г '⊢' t '∈' T" (at level 40).
Reserved Notation "Г '⊢' T '<:' U" (at level 40).
Inductive typing_relation : context -> term -> type -> Prop := ...
where "Γ '⊢' t '∈' T" := (typing_relation Γ t T).
Inductive subtyping_relation : context -> type -> type -> Prop := ...
where "Г '⊢' T '<:' U" := (subtyping_relation Γ T U).
As I understand, Coq will not allow this because the ⊢ operator is overloaded in those definitions.
How could I make Coq infer the definition of an overloaded operator (in this case, ⊢) based on the types of its arguments (e.g. term vs type) (and/or based on the other operators that are part of the notation, e.g. ∈ vs <:)?
(Note that using different symbols would not be an option, because my Coq program defines several typing and subtyping relations.)
EDIT: Here is a minimal example:
Inductive type : Type :=
| TBool : type.
Inductive term : Type :=
| tvar : nat -> term.
Definition context := nat -> (option type).
Reserved Notation "G '⊢' t '∈' T" (at level 40).
Inductive typing_relation : context -> term -> type -> Prop :=
| T_Var : forall G x T,
G x = Some T ->
G ⊢ tvar x ∈ T
where "G '⊢' t '∈' T" := (typing_relation G t T).
Reserved Notation "G '⊢' T '<:' U" (at level 40).
Inductive subtype_relation : context -> type -> type -> Prop :=
| S_Refl : forall G T,
G ⊢ T <: T
where "G '⊢' T '<:' U" := (subtype_relation G T U).
This results in the error:
Syntax error: '<:' or '∈' expected after [constr:operconstr level 200] (in [constr:operconstr]).
The reason is that you cannot use <: like that, because <: is already defined as Coq's typecast notation. It acts as if it was defined like so
Reserved Notation "t <: T" (at level 100, right associativity).
The situation is analogous to the one described in The Coq Reference Manual (§12.1.3):
In the last case though, there is a conflict with the notation for type casts. This last notation, as shown by the command Print Grammar constr. is at level 100. To avoid x : A being parsed as a type cast, it is necessary to put x at a level below 100, typically 99.
Here is a possible solution for your situation:
Reserved Notation "G '⊢' t '∈' T" (at level 40, t at level 99).
Reserved Notation "G '⊢' T '<:' U" (at level 40, T at level 99).
Related
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.
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.
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).
I some times see this syntax in Coq to represent certain types/sets such as in printing information about existential variables:
?T : [ |- Set]
?T0 : [ x : ?T |- Set ]
I don't know how to search for this syntax.
What does it mean?
Is the first one the same as
? T : Set
?
Suppose we have a term with a certain type.
Variable B : nat -> nat.
Check B.
(*
B
: nat -> nat
*)
If we create another term using B it may or may not type check, i.e. B true is not typeable.
Fail Check B true.
(*
Error message:
The term "true" has type "bool" while it is expected to have type "nat".
*)
Coq allows wildcards in terms and then tries to figure out the type itself.
Check B _.
(*
B ?n
: nat
where
?n : [ |- nat]
*)
Here Coq says that the type of B _ is nat, but only
under the assumption that the argument
(named ?n) is of type nat. Or otherwise put, "under the assumption that one can infer that the type of ?n is nat from the empty context".
Sometimes more stuff is found on the left side of the "turnstile" symbol |-.
Variable x:nat.
Check _ x.
(*
?y x
: ?T#{x:=x}
where
?y : [ |- forall x : nat, ?T]
?T : [x : nat |- Type]
*)
Above the underscore is called ?y and the type of (?y x) is a dependent type ?T that depends on x. ?T is only typable (to a Type) in a context where x is a nat.
If x is not a nat, then ?T is not typable.
I might be mistaken, but the first one should be read as "the existential variable named T is of type Set" and the second should be read as "the existential variable named T0 is of type Set, in a context where the variable x is of type ?T", meaning that the term which will fill the second hole might depend on some variable named x.
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).