Tactic index
In this document we illustrate various Rocq tactics that appear in the course. They are not ordered alphabetically but rather follow an order more or less in line with the lecture notes.
intro
Usage: intro h, where h is a new name.
intro h introduces hypothesis h into the context
It works when the goal is equivalent to A -> B or forall (x : A), B, in
which case h is of type A and the goal becomes B (where x is replaced
by h when it appears).
forall (P : nat -> Prop) (x : nat), P x -> P (0 + x)forall (P : nat -> Prop) (x : nat), P x -> P (0 + x)Q: nat -> Propforall x : nat, Q x -> Q (0 + x)Q: nat -> Prop
y: natQ y -> Q (0 + y)Abort.Q: nat -> Prop
y: nat
h: Q yQ (0 + y)
split
Usage: split.
Applies when the goal is morally a conjunction of subgoals and asks the user
to prove those subgoals instead.
This works for conjunction (A /\ B) and nullary-conjunction (True):
True /\ True /\ TrueTrue /\ True /\ TrueTrueTrue /\ Truesplit.TrueTrue /\ TrueTrueTruesplit.Truesplit. Abort.True
More advanced. It in facts applies whenever the goal is an inductive type which has exactly one constructor and requires you to give its arguments one by one.
unit * (0 = 0)unit * (0 = 0)unit0 = 0split.unitsplit. Abort.0 = 0
destruct
Usage: destruct t as p, where t is an expression (often a variable) and
p is an intropattern (explained below).
Performs case analysis on t, generating as many goals as possible ways to
construct t (for instance, for t : bool, there are two such cases), and
replacing t in the goal by the corresponding constructions (so true and
false in the bool case).
As a first approximation, you can see p as the list of cases, separated by
pipes (|), and for each of them you provide the names to be used for the
introduced constants, separated by spaces.
See for instance, case analysis on natural numbers:
forall (P : nat -> Prop) (n : nat), P nforall (P : nat -> Prop) (n : nat), P nP: nat -> Propforall n : nat, P nP: nat -> Prop
n: natP nAbort.P: nat -> PropP 0P: nat -> Prop
m: natP (S m)
The intropattern contains no name for the 0 case, since 0 takes no argument,
and exactly one for the successor case, since S takes one argument.
Advanced variant: destruct t as p eqn:e.
This version lets you additionally record an equality e : t = _ where _
stands for the construction in each goal.
forall (P : bool -> Prop) (b : bool), P bforall (P : bool -> Prop) (b : bool), P bp: bool -> Propforall b : bool, p bp: bool -> Prop
b: boolp bAbort.p: bool -> Prop
b: bool
e: b = truep truep: bool -> Prop
b: bool
e: b = falsep false
intros
Usage: intros p1 p2 ... pN, where each pI is an intropattern, the list
can be empty.
At first glance, it behaves like a succession of intro:
indeed, intros a b c. is equivalent to intro a. intro b. intro c.
When no argument is provided, it introduces as much as it can, using
auto-generated names.
intros can in fact do much more, since intropatterns can be used to also
perform case analysis.
forall (P : bool -> nat -> Type) (b : bool) (n : nat), P b nforall (P : bool -> nat -> Type) (b : bool) (n : nat), P b nAbort.P: bool -> nat -> TypeP true 0P: bool -> nat -> TypeP true 1P: bool -> nat -> Type
k: natP true (S (S k))P: bool -> nat -> TypeP false 0P: bool -> nat -> TypeP false 1P: bool -> nat -> Type
k: natP false (S (S k))
apply
Usage: apply t, where t is an expression (often a lemma or an
assumption).
Unifies the type of t with the goal to attempt to conclude using t.
If successful, the resulting goals will correspond to arguments to t that must
be provided to conclude, or none if t is sufficient.
From Stdlib Require Import List.forall (A : Type) (l : list A), l ++ nil = lforall (A : Type) (l : list A), l ++ nil = lapply app_nil_r. Abort.A: Type
l: list Al ++ nil = lforall P Q R : Type, (P -> Q -> R) -> Rforall P Q R : Type, (P -> Q -> R) -> RP, Q, R: Type
h: P -> Q -> RRAbort.P, Q, R: Type
h: P -> Q -> RPP, Q, R: Type
h: P -> Q -> RQ
Variant: apply f in h where h is an hypothesis.
This time it tries to unify the type of h with one of the arguments of f.
forall P Q : nat -> Type, (forall n : nat, P n -> Q 5 -> Q (n + 2)) -> P 10 -> Q 12forall P Q : nat -> Type, (forall n : nat, P n -> Q 5 -> Q (n + 2)) -> P 10 -> Q 12P, Q: nat -> Type
hPQ: forall n : nat, P n -> Q 5 -> Q (n + 2)
hP: P 10Q 12Abort.P, Q: nat -> Type
hPQ: forall n : nat, P n -> Q 5 -> Q (n + 2)
hP: Q (10 + 2)Q 12P, Q: nat -> Type
hPQ: forall n : nat, P n -> Q 5 -> Q (n + 2)
hP: P 10Q 5
Variant: apply f in h as g, lets you additionally give a new name (g) to
the generated hypothesis, while keeping h in scope.
forall P Q : nat -> Type, (forall n : nat, P n -> Q 5 -> Q (n + 2)) -> P 10 -> Q 12forall P Q : nat -> Type, (forall n : nat, P n -> Q 5 -> Q (n + 2)) -> P 10 -> Q 12P, Q: nat -> Type
hPQ: forall n : nat, P n -> Q 5 -> Q (n + 2)
hP: P 10Q 12Abort.P, Q: nat -> Type
hPQ: forall n : nat, P n -> Q 5 -> Q (n + 2)
hP: P 10
hQ: Q (10 + 2)Q 12P, Q: nat -> Type
hPQ: forall n : nat, P n -> Q 5 -> Q (n + 2)
hP: P 10Q 5
Variant: apply f,g,h, lets you chain several apply in a row by seprating
them with commas.
forall P Q R : Type, (P -> Q) -> (Q -> R) -> P -> Rforall P Q R : Type, (P -> Q) -> (Q -> R) -> P -> Rapply hQR, hPQ, hP. Abort.P, Q, R: Type
hPQ: P -> Q
hQR: Q -> R
hP: PR
assumption
Usage: assumption.
Concludes the goal if one of the assumptions matches it exactly.
forall (P Q : Prop) (R : Type), (P -> Q -> R) -> P /\ Q -> Rforall (P Q : Prop) (R : Type), (P -> Q -> R) -> P /\ Q -> RP, Q: Prop
R: Type
hPQR: P -> Q -> R
hP: P
hQ: QRP, Q: Prop
R: Type
hPQR: P -> Q -> R
hP: P
hQ: QPP, Q: Prop
R: Type
hPQR: P -> Q -> R
hP: P
hQ: QQassumption.P, Q: Prop
R: Type
hPQR: P -> Q -> R
hP: P
hQ: QPassumption. Abort.P, Q: Prop
R: Type
hPQR: P -> Q -> R
hP: P
hQ: QQ
left
Usage: left.
Lets you prove a goal of the form A \/ B by requiring you to prove A
instead.
forall A B : Prop, A \/ Bforall A B : Prop, A \/ BA, B: PropA \/ BAbort.A, B: PropA
right
Usage: right.
Lets you prove a goal of the form A \/ B by requiring you to prove B
instead.
Basically the same as left, but going right instead.
forall A B : Prop, A \/ Bforall A B : Prop, A \/ BA, B: PropA \/ BAbort.A, B: PropB
exfalso
Usage: exfalso.
Replaces the current goal with False, using the ex falso quod libet
principle, also known as principle of explosion: you can deduce anything from
False.
forall (P : Prop) (Q : Type), P -> ~ P -> Qforall (P : Prop) (Q : Type), P -> ~ P -> QP: Prop
Q: Type
hP: P
hnP: ~ PQAbort.P: Prop
Q: Type
hP: P
hnP: ~ PFalse
simpl
Usage: simpl.
Performs computation in the current goal to "simplify" it (in some sense).
forall P : nat -> Type, P 10 -> P (4 + 6)forall P : nat -> Type, P 10 -> P (4 + 6)P: nat -> Type
hP: P 10P (4 + 6)Abort.P: nat -> Type
hP: P 10P 10
Variant: simpl in h, where h is an assumption.
forall P : nat -> Type, P (7 + 3) -> P 10forall P : nat -> Type, P (7 + 3) -> P 10P: nat -> Type
hP: P (7 + 3)P 10Abort.P: nat -> Type
hP: P 10P 10
Variant: simpl in *.
Simplifies all hypotheses and the goal at once.
forall P : nat -> Type, P (2 + 2) -> P (4 + 8) -> P (27 + 5)forall P : nat -> Type, P (2 + 2) -> P (4 + 8) -> P (27 + 5)P: nat -> Type
h4: P (2 + 2)
h12: P (4 + 8)P (27 + 5)Abort.P: nat -> Type
h4: P 4
h12: P 12P 32
Variant: simpl n, where n is a constant name.
Perform computation only for n.
10 + 2 - (3 + 5) = 1910 + 2 - (3 + 5) = 19Abort.12 - 8 = 19
reflexivity
Usage: exfalso.
Prove goals of the shape t = t, it thus corresponds to reflexivity of
equality.
f_equal
Usage: f_equal.
Turns a goal of the shape f x y … z = f x' y' … z' into x = x', y = y'
and z = z'.
forall (A B C D : Type) (f : A -> B -> C -> D) (x : A) (y : B) (z : C) (x' : A) (y' : B) (z' : C), f x y z = f x' y' z'forall (A B C D : Type) (f : A -> B -> C -> D) (x : A) (y : B) (z : C) (x' : A) (y' : B) (z' : C), f x y z = f x' y' z'A, B, C, D: Type
f: A -> B -> C -> D
x: A
y: B
z: C
x': A
y': B
z': Cf x y z = f x' y' z'Abort.A, B, C, D: Type
f: A -> B -> C -> D
x: A
y: B
z: C
x': A
y': B
z': Cx = x'A, B, C, D: Type
f: A -> B -> C -> D
x: A
y: B
z: C
x': A
y': B
z': Cy = y'A, B, C, D: Type
f: A -> B -> C -> D
x: A
y: B
z: C
x': A
y': B
z': Cz = z'
induction
Usage: induction t as p.
This works a bit like destruct except that it uses the induction principle
corresponding to the type of t and additionally gives induction hypotheses
in the recursive cases.
The intropattern p must also name said induction hypotheses.
forall n : nat, n + 0 = nforall n : nat, n + 0 = nn: natn + 0 = n0 + 0 = 0m: nat
ih: m + 0 = mS m + 0 = S mreflexivity.0 + 0 = 0m: nat
ih: m + 0 = mS m + 0 = S mm: nat
ih: m + 0 = mS (m + 0) = S mapply ih. Abort.m: nat
ih: m + 0 = mm + 0 = m
Variant: induction t as p in x, y, …, z |- *, where x, y, …, z is a
comma-separated sequence of assumptions (in the context) to generalise over.
It works like induction above but produce a stronger induction hypothesis
by generalising over the listed constants.
n, m, k: natk * (n + m) = k * n + k * mn, m, k: natk * (n + m) = k * n + k * mn, m: nat0 * (n + m) = 0 * n + 0 * mn, m, k: nat
ihk: forall n m : nat, k * (n + m) = k * n + k * mS k * (n + m) = S k * n + S k * mn, m: nat0 * (n + m) = 0 * n + 0 * mreflexivity.n, m: nat0 = 0Abort.n, m, k: nat
ihk: forall n m : nat, k * (n + m) = k * n + k * mS k * (n + m) = S k * n + S k * m
rewrite
Usage: rewrite t, where t is a term (for instance lemma or assumption).
Assuming t is a (possibly universally quantified) equality lhs = rhs,
replaces occurrences of lhs in the goal by rhs.
forall (A : Type) (P : A -> Type) (a b : A), a = b -> P b -> P aforall (A : Type) (P : A -> Type) (a b : A), a = b -> P b -> P aA: Type
P: A -> Type
a, b: A
e: a = b
h: P bP aAbort.A: Type
P: A -> Type
a, b: A
e: a = b
h: P bP b
Variant: rewrite <- t.
Similar, but replaces rhs by lhs instead.
forall (A : Type) (P : A -> Type) (a b : A), a = b -> P a -> P bforall (A : Type) (P : A -> Type) (a b : A), a = b -> P a -> P bA: Type
P: A -> Type
a, b: A
e: a = b
h: P aP bAbort.A: Type
P: A -> Type
a, b: A
e: a = b
h: P aP a
Variant: rewrite t in h, where h is an assumption.
Similarly, but the replacement is done in h.
forall (A : Type) (P : A -> Type) (a b : A), a = b -> P a -> P bforall (A : Type) (P : A -> Type) (a b : A), a = b -> P a -> P bA: Type
P: A -> Type
a, b: A
e: a = b
h: P aP bAbort.A: Type
P: A -> Type
a, b: A
e: a = b
h: P bP b
Variant: rewrite rs, where rs is a list of rewrites such as t or
<- t.
Performs several rewrites in succession.
X: Type
P: X -> Type
a, b, c: X
e: a = b
e': c = bP aX: Type
P: X -> Type
a, b, c: X
e: a = b
e': c = bP aAbort.X: Type
P: X -> Type
a, b, c: X
e: a = b
e': c = bP c
specialize
Usage: specialize (h u v … w), where h is an assumption, and u, v, … w
are terms.
Replaces hyopthesis h with its instantiation with the provided arguments.
X, Y, Z, A: Type
h: X -> Y -> Z -> AX -> (Y -> Z) -> Y -> AX, Y, Z, A: Type
h: X -> Y -> Z -> AX -> (Y -> Z) -> Y -> AX, Y, Z, A: Type
h: X -> Y -> Z -> A
x: X
z: Y -> Z
y: YAX, Y, Z, A: Type
h: Y -> Z -> A
x: X
z: Y -> Z
y: YAX, Y, Z, A: Type
h: Y -> Z -> A
x: X
z: Z
y: YAAbort.X, Y, Z, A: Type
h: A
x: X
z: Z
y: YA
Variant: specialize (h u v … w) as g, where g is a new name.
Produce a new hypothesis g corresponding to the instantiation of h with
the provided arguments. h is left unchanged.
X, Y, Z, A: Type
h: X -> Y -> Z -> AX -> (Y -> Z) -> Y -> AX, Y, Z, A: Type
h: X -> Y -> Z -> AX -> (Y -> Z) -> Y -> AX, Y, Z, A: Type
h: X -> Y -> Z -> A
x: X
z: Y -> Z
y: YAX, Y, Z, A: Type
h: X -> Y -> Z -> A
x: X
z: Y -> Z
y: Y
h': Y -> Z -> AAX, Y, Z, A: Type
h: X -> Y -> Z -> A
x: X
z: Y -> Z
y: Y
h': Y -> Z -> A
z': ZAAbort.X, Y, Z, A: Type
h: X -> Y -> Z -> A
x: X
z: Y -> Z
y: Y
h': A
z': ZA
Variant: specialize (h u v … w) as p, where p is an intropattern.
Behaves like specialize (h u v … w) followed by destruct h as p.
h: nat -> natnath: nat -> natnatAbort.natm: natnat