File tree 1 file changed +40
-14
lines changed
1 file changed +40
-14
lines changed Original file line number Diff line number Diff line change @@ -3,6 +3,44 @@ Inductive foo :=
3
3
| bar1
4
4
| bar2.
5
5
6
+ Definition ctornum f :=
7
+ match f with
8
+ | bar0 => 1
9
+ | bar1 => 2
10
+ | bar2 => 3
11
+ end .
12
+
13
+ (* an illustration of constructor backtracking *)
14
+ Goal { f:foo | ctornum f = 3 }.
15
+ unshelve eapply exist; [ constructor | match goal with
16
+ | |- ?g => idtac g
17
+ end ; reflexivity ].
18
+ Qed .
19
+
20
+ (* same as above, but more directly *)
21
+ Definition foo_by_ctornum : {f:foo | ctornum f = 3}.
22
+ Proof .
23
+ (* the tactic after the ; works only because [constructor] backtracks until
24
+ [reflexivity] succeeds. *)
25
+ unshelve refine (exist _ _ _); [ constructor | reflexivity].
26
+ Defined .
27
+
28
+ Inductive NumIsGood (n:nat) : Prop :=
29
+ | Good0 (H: n = 0)
30
+ | Good3 (H: n = 3)
31
+ | Good7 (H: n = 7)
32
+ .
33
+
34
+ Lemma three_is_good : NumIsGood 3.
35
+ Proof .
36
+ (* [constructor] on its own would pick [Good0], resulting in an unprovable
37
+ goal. Adding [solve [ eauto ]] means the whole tactic backtracks on the choice
38
+ of constructor. *)
39
+ constructor; solve [ eauto ].
40
+ Qed .
41
+
42
+ (* a fun but not very useful thing we can do with constructor backtracking is to
43
+ print them out: *)
6
44
Ltac constructors t :=
7
45
let make_constructors :=
8
46
unshelve eapply exist;
@@ -15,20 +53,8 @@ Ltac constructors t :=
15
53
16
54
Goal True.
17
55
constructors foo.
18
- (* bar0
56
+ (* output:
57
+ bar0
19
58
bar1
20
59
bar2 *)
21
60
Abort .
22
-
23
- Definition ctornum f :=
24
- match f with
25
- | bar0 => 1
26
- | bar1 => 2
27
- | bar2 => 3
28
- end .
29
-
30
- Goal { f:foo | ctornum f = 3 }.
31
- unshelve eapply exist; [ econstructor | match goal with
32
- | |- ?g => idtac g
33
- end ; reflexivity ].
34
- Qed .
You can’t perform that action at this time.
0 commit comments