Existential variables¶
Existential variables represent as yet unknown values.
term_evar::=
_
|
?[ ident ]
|
?[ ?ident ]
|
?ident @{ ident := term+; }?
Coq terms can include existential variables that represent unknown subterms that are eventually replaced with actual subterms.
Existential variables are generated in place of unsolved implicit
arguments or “_” placeholders when using commands such as Check
(see
Section Requests to the environment) or when using tactics such as
refine
, as well as in place of unsolved instances when using
tactics such that eapply
. An existential
variable is defined in a context, which is the context of variables of
the placeholder which generated the existential variable, and a type,
which is the expected type of the placeholder.
As a consequence of typing constraints, existential variables can be duplicated in such a way that they possibly appear in different contexts than their defining context. Thus, any occurrence of a given existential variable comes with an instance of its original context. In the simple case, when an existential variable denotes the placeholder which generated it, or is used in the same context as the one in which it was generated, the context is not displayed and the existential variable is represented by “?” followed by an identifier.
- Parameter identity : forall (X:Set), X -> X.
- identity is declared
- Check identity _ _.
- identity ?X ?y : ?X where ?X : [ |- Set] ?y : [ |- ?X]
- Check identity _ (fun x => _).
- identity (forall x : ?S, ?S0) (fun x : ?S => ?y) : forall x : ?S, ?S0 where ?S : [ |- Set] ?S0 : [x : ?S |- Set] ?y : [x : ?S |- ?S0]
In the general case, when an existential variable ?ident
appears
outside its context of definition, its instance, written in the
form { ident := term*; }
, is appended to its name, indicating
how the variables of its defining context are instantiated.
Only the variables that are defined in another context are displayed:
this is why an existential variable used in the same context as its
context of definition is written with no instance.
This behaviour may be changed: see Explicit displaying of existential instances for pretty-printing.
- Check (fun x y => _) 0 1.
- (fun x y : nat => ?y) 0 1 : ?T@{x:=0; y:=1} where ?T : [x : nat y : nat |- Type] ?y : [x : nat y : nat |- ?T]
Existential variables can be named by the user upon creation using
the syntax ?[ident]
. This is useful when the existential
variable needs to be explicitly handled later in the script (e.g.
with a named-goal selector, see Goal selectors).
Inferable subterms¶
Expressions often contain redundant pieces of information. Subterms that can be
automatically inferred by Coq can be replaced by the symbol _
and Coq will
guess the missing piece of information.
Explicit displaying of existential instances for pretty-printing¶
-
Flag
Printing Existential Instances
¶ This flag (off by default) activates the full display of how the context of an existential variable is instantiated at each of the occurrences of the existential variable.
- Check (fun x y => _) 0 1.
- (fun x y : nat => ?y) 0 1 : ?T@{x:=0; y:=1} where ?T : [x : nat y : nat |- Type] ?y : [x : nat y : nat |- ?T]
- Set Printing Existential Instances.
- Check (fun x y => _) 0 1.
- (fun x y : nat => ?y@{x:=x; y:=y}) 0 1 : ?T@{x:=0; y:=1} where ?T : [x : nat y : nat |- Type] ?y : [x : nat y : nat |- ?T@{x:=x; y:=y}]
Solving existential variables using tactics¶
Instead of letting the unification engine try to solve an existential
variable by itself, one can also provide an explicit hole together
with a tactic to solve it. Using the syntax ltac:(
tacexpr
)
, the user
can put a tactic anywhere a term is expected. The order of resolution
is not specified and is implementation-dependent. The inner tactic may
use any variable defined in its scope, including repeated alternations
between variables introduced by term binding as well as those
introduced by tactic binding. The expression tacexpr
can be any tactic
expression as described in Ltac.
- Definition foo (x : nat) : nat := ltac:(exact x).
- foo is defined
This construction is useful when one wants to define complicated terms using highly automated tactics without resorting to writing the proof-term by means of the interactive proof engine.