-
Notifications
You must be signed in to change notification settings - Fork 78
/
QUICK_REFERENCE.txt
2391 lines (1962 loc) · 90.5 KB
/
QUICK_REFERENCE.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
thm:
REFL `x`
gives `|- x = x`
TRANS `ASM1 |- a = b` `ASM2 |- b = c`
gives `ASM1+ASM2 |- a = c`
MK_COMB (`ASM1 |- f = g`, `ASM2 |- a = b`)
gives `ASM1+ASM2 |- (f a) = (g b)`
ABS `x` `ASM1{-x} |- a=b`
gives `ASM1 |- \x.a = \x.b`
BETA is useless; use BETA_CONV
ASSUME `a`
gives `a |- a`
EQ_MP `ASM1 |- a = b` `ASM2 |- a`
gives `ASM1+ASM2 |- b`
DEDUCT_ANTISYM_RULE `ASM1 |- a` `ASM2 |- b`
gives `(ASM1-{b})+(ASM2-{a}) |- a=b`
INST_TYPE instantiation theorem
gives a new theorem with type variables instantiated
INST instantiation theorem
gives a new theorem with variables instantiated
equal:
BETA_CONV `(\x. A) y`
gives `|- (\x. A) y = A[y/x]`
AP_TERM `f` `ASM1 |- a = b`
gives `ASM1 |- (f a) = (f b)`
AP_THM `ASM1 |- f = g` `a`
gives `ASM1 |- (f a) = (g a)`
SYM `ASM1 |- a = b`
gives `ASM1 |- b = a`
ALPHA `(\x.x)` `(\y.y)`
gives `|- (\x.x) = (\y.y)`
ALPHA_CONV `y` `(\x.x)`
gives `|- (\x.x) = (\y.y)`
GEN_ALPHA_CONV `y` `!x. P[x]`
gives `|- (!x. P[x]) = (!y. P[y])` (it looks inside one level of application)
MK_BINOP `(+)` (`ASM1 |- a = b`, `ASM2 |- c = d`)
gives `ASM1+ASM2 |- a + c = b + d`
A conversion takes a term and returns an equality theorem with the term on
the lhs (or it fails).
NO_CONV is a conversion which always fails.
ALL_CONV is a conversion which always succeeds without changing the term.
c1 THENC c2 rewrites with c1 then c2.
c1 ORELSEC c2 rewrites with c1; if it fails, it rewrites with c2 instead.
FIRST_CONV [c1;...;cn] rewrites with the first non-failing conversion in
the list.
EVERY_CONV [c1;...;cn] rewrites with the first conversion, then the
second, then ... then the last.
REPEATC c rewrites with c until it fails (and returns the result of the
last successful rewrite).
CHANGED_CONV c rewrites with c, but fails if the result is alpha-equivalent
to the original term.
TRY_CONV c rewrites with c; if it fails, it does not change the term
(and does not fail).
RATOR_CONV c uses the conversion to rewrite the operator of a combination.
RAND_CONV c uses the conversion to rewrite the operand of a combination.
LAND_CONV c uses the conversion to rewrite the first argument of
a binary function.
COMB2_CONV c1 c2 uses c1 to rewrite the operator and c2 to rewrite the
operand of a combination.
COMB_CONV c rewrites both the operator and operand of a combination with c.
ABS_CONV c rewrites the body of an abstraction with c.
BINDER_CONV c rewrites the body of an abstraction or of a
binder/abstraction combination.
SUB_CONV c either rewrites both parts of a combination, or the body
of an abstraction, or does nothing (it never fails).
BINOP_CONV c rewrites both arguments of a binary function.
THENQC c1 c2 is like (c1 THENC c2) ORELSEC c1 ORELSEC c2
THENCQC c1 c2 is like (c1 THENC c2) ORELSEC c1
REPEATQC c rewrites with c one or more times, until it fails (returning
the last succeeding rewrite; if the initial rewrite fails,
then REPEATQC fails)
COMB2_QCONV c1 c2 is like
(RATOR_CONV c1 THENC RAND_CONV c2) ORELSEC RATOR_CONV c1 ORELSEC RAND_CONV c2
COMB_QCONV c = COMB2_QCONV c c
SUB_QCONV c is like ABS_CONV c ORELSEC COMB_QCONV c
ONCE_DEPTH_QCONV c uses c to rewrite all maximal applicable terms
(terms which are not properly contained in another
applicable term). Fails if c does not apply to any terms.
DEPTH_QCONV c repeatedly rewrites with c (in a single bottom-up sweep),
failing if c does not apply anywhere.
REDEPTH_QCONV c rewrites with c (in a bottom-up sweep); after any
successful rewrite, it starts over again at the leaves
of the new term. Fails if c does not apply anywhere.
TOP_DEPTH_QCONV c repeatedly rewrites with c top-to-bottom;
recursively do something like:
do (rewrite current until no change)
then rewrite children with TOP_DEPTH_QCONV
until no change
TOP_SWEEP_QCONV c rewrite with c top-to-bottom; something like:
(rewrite current until no change)
then rewrite children with TOP_SWEEP_QCONV
ONCE_DEPTH_CONV, DEPTH_CONV, REDEPTH_CONV, TOP_DEPTH_CONV, TOP_SWEEP_CONV:
like the QCONV variants, except they never fail
SINGLE_DEPTH_CONV c rewrites maximal applicable subterms with c,
then rewrites parents of changed terms bottom-up
DEPTH_BINOP_CONV op c
For example, DEPTH_BINOP_CONV `+` c rewrites
x,y,z,w in `(x + ((y + z) + w))` (fails if any
of these rewrites fail)
PATH_CONV path c
For example, PATH_CONV ["b";"l";"r";"r"] c rewrites the
operand of the operand of the operator of the abstraction body
with c.
SYM_CONV rewrites `a = b` to `b = a`
CONV_RULE c th uses c to rewrite the conclusion of the theorem
(and return a new theorem).
SUBS_CONV ths is a conversion. It takes its list of equality
theorems and rewrites (anywhere in its argument term)
any lhs to its corresponding rhs (matching with alpha-equivalence).
BETA_RULE takes a theorem, does all possible beta reductions, and
returns the new theorem.
GSYM applies symmetry on all outermost equalities in the conclusion
of a theorem.
SUBS applies SUBS_CONV to the conclusion of a theorem.
CACHE_CONV c is equivalent to c, except that it caches all
conversion applications.
bool:
PINST tyin tmin th instantiates types in th according to tyin and terms
according to tmin.
PROVE_HYP th1 th2
If the conclusion of th1 is a hypothesis of th2, then returns th2
except that this hypothesis is replaced by the hypotheses of th1; otherwise
returns th2 unchanged.
T_DEF: `T = ((\x:bool. x) = (\x:bool. x))`
TRUTH: `|- T`
EQT_ELIM `ASM1 |- a = T` gives `ASM1 |- a`
EQT_INTRO `ASM1 |- a` gives `ASM1 |- a = T`
AND_DEF: `(/\) = \t1 t2. (\f:bool->bool->bool. f t1 t2) = (\f. f T T)`
CONJ `ASM1 |- a` `ASM2 |- b` gives `ASM1+ASM2 |- a /\ b`
CONJUNCT1 `ASM |- a /\ b` gives `ASM1 |- a`
CONJUNCT2 `ASM |- a /\ b` gives `ASM1 |- b`
CONJ_PAIR th = (CONJUNCT1 th, CONJUNCT2 th)
CONJUNCTS th gives a list of theorems, one for each conjunct of the
conclusion of th (no matter how they are associated)
IMP_DEF: `(==>) = \t1 t2. t1 /\ t2 = t1`
MP `ASM1 |- a ==> b` `ASM2 |- a` gives `ASM1+ASM2 |- b`
DISCH `a` `ASM,a |- b` gives `ASM |- a ==> b`
DISCH_ALL repeats DISCH until there are no more hypotheses.
UNDISCH `ASM |- a ==> b` gives `ASM,a |- b`
UNDISCH_ALL repeats UNDISCH until the conclusion is not an implication
IMP_ANTISYM_RULE `ASM1 |- a ==> b` `ASM2 |- b ==> a` gives `ASM1+ASM2 |- a = b`
ADD_ASSUM `a` `ASM |- b` gives `ASM,a |- b`
EQ_IMP_RULE `ASM |- (a:bool) = b` gives (`ASM |- a ==> b`, `ASM |- b ==> a`)
IMP_TRANS `ASM1 |- a ==> b` `ASM2 |- b ==> c` gives `ASM1+ASM2 |- a ==> c`
FORALL_DEF: `(!) = \P:A->bool. P = \x. T`
SPEC `a` `ASM |- !x.P[x]` gives `ASM |- P[a]`
SPECL [`a`;`b`;`c`] `ASM |- !x y z.P[x,y,z]` gives `ASM |- P[a,b,c]`
SPEC_VAR `ASM |- !x.P[x]` gives (`x17`, `ASM |- P[x17]`)
SPEC_ALL repeats SPEC_VAR until the conclusion is not a "forall", and returns
the final theorem.
ISPEC is like SPEC, except that the specialized term may be an instance
of the type of the quantified variable (in which case the theorem
is type-instantiated first), rather than matching exactly.
ISPECL is like SPECL with type instantiations.
GEN `x` `ASM |- P[x]` gives `ASM |- !x. P[x]` (if x is not free in ASM)
GENL [`x`;`y`;`z`] `ASM |- P[x,y,z]` gives `ASM |- !x y z. P[x,y,z]`
GEN_ALL generalizes over all variables free in the conclusion but not
in the assumptions
EXISTS_DEF: `(?) = \P:A->bool. !Q. (!x. P x ==> Q) ==> Q`
EXISTS (`?x. P[x]`,`a`) `ASM |- P[a]` gives `ASM |- ?x. P[x]`
SIMPLE_EXISTS `x` `ASM |- P[x]` gives `ASM |- ?x. P[x]`
CHOOSE (`x`,`ASM1 |- ?y.P[y]`) `ASM2,P[x] |- a` gives `ASM1+ASM2 |- a`
SIMPLE_CHOOSE `x` `ASM,P[x] |- a` gives `ASM,?x.P[x] |- a` (P[x] must be
the first hypothesis)
OR_DEF: `(\/) = \t1 t2. !t. (t1 ==> t) ==> (t2 ==> t) ==> t`
DISJ1 `ASM |- a` `b` gives `ASM |- a \/ b`
DISJ2 `a` `ASM |- b` gives `ASM |- a \/ b`
DISJ_CASES `ASM1 |- a \/ b` `ASM2,a |- c` `ASM3,b |- c` gives
`ASM1,ASM2,ASM3 |- c`
SIMPLE_DISJ_CASES `ASM1,a |- c` `ASM2,b |- c` gives
`ASM1,ASM2,a \/ b |- c` (a and b must be the first
hypotheses)
F_DEF: `F = !t:bool. t`
NOT_DEF: `(~) = \t. t ==> F`
NOT_ELIM `ASM |- ~a` gives `ASM |- a ==> F`
NOT_INTRO `ASM |- a ==> F` gives `ASM |- ~a`
EQF_INTRO `ASM |- ~a` gives `ASM |- a = F`
EQF_ELIM `ASM |- a = F` gives `ASM |- ~a`
NEG_DISCH `a` `ASM,a |- F` gives `ASM |- ~a` (if the conclusion of the
initial theorem is not F, then NEG_DISCH acts like DISCH)
CONTR `a` `ASM |- F` gives `ASM |- a`
EXISTS_UNIQUE_DEF: `(?!) = \P:A->bool. ((?) P) /\ (!x y. ((P x) /\ (P y)) ==> (x = y))`
EXISTENCE `ASM |- ?!x. P[x]` gives `ASM |- ?x. P[x]`
drule:
MK_CONJ `ASM1 |- a = b` `ASM2 |- c = d` gives `ASM1,ASM2 |- a /\ c = b /\ d`
MK_DISJ `ASM1 |- a = b` `ASM2 |- c = d` gives `ASM1,ASM2 |- a \/ c = b \/ d`
MK_FORALL `x` `ASM |- a = b` gives `ASM |- (!x.a) = (!x.b)`
MK_EXISTS `x` `ASM |- a = b` gives `ASM |- (?x.a) = (?x.b)`
BETAS_CONV (n:int) is a conversion which rewrites with BETA_CONV n times.
(so BETAS_CONV 3 rewrites `(\x y z.P[x,y,z]) a b c` to `P[a,b,c]`)
INSTANTIATE takes an "instantiation" and a theorem and instantiates
the theorem. (I haven't figured out yet what an "instantiation" is.)
INSTANTIATE_ALL has the same type as INSTANTIATE.
For the rest of the file, I will treat '@' as a metavariable for
an instantiation (written postfix). For instance, I may mention
the terms `a ==> b`, `a@`, and `b@`; this means that
`a@ ==> b@` is an instantiation of `a ==> b`.
In some cases where I use this notation, universal quantification is
allowed; that is, where I mention terms `a` and `a@`, the implementation
would allow `!x. P[x]` and `P[b]`.
PART_MATCH partfn th tm matches (partfn (concl (SPEC_ALL th))) against tm
and instantiates the theorem appropriately.
MATCH_MP ith th is like MP, except it uses matching instead of
requiring an exact match.
HIGHER_REWRITE_CONV ths top
A conversion which finds the first largest (if top == true) or smallest
(if top == false) subterm which matches (using higher-order matching)
a lhs of a conclusion in ths, and rewrites it.
tactics:
t1 THEN t2
Apply t1, then apply t2 to all subgoals created.
t THENL [t1;t2;...;tn]
Apply t, then apply t1 to the first subgoal, ..., tn to the last subgoal
(there must be exactly n subgoals).
t1 ORELSE t2
Apply t1; if it fails, apply T2.
FAIL_TAC s
A tactic which always fails (with error message s).
NO_TAC
A tactic which always fails.
ALL_TAC
A tactic which does nothing (the identity tactic).
TRY t = tac ORELSE ALL_TAC
REPEAT t
Apply t, then apply it again to all subgoals, etc.; until it fails.
EVERY [t1;...;tn] = t1 THEN ... THEN tn
FIRST [t1;...;tn] = t1 ORELSE ... ORELSE tn
MAP_EVERY tf [x1;...;xn] = tf x1 THEN ... THEN tf xn
MAP_FIRST tf [x1;...;xn] = tf x1 ORELSE ... ORELSE tf xn
CHANGED_TAC t
Apply t; fail if the result is a single subgoal which is equal to the
original goal (warning: does not use alpha-equivalence!)
A "theorem tactic" is a function from theorems to tactics.
A "theorem tactical" is a function from theorem tactics to theorem tactics.
Equivalently: a theorem tactical is a function from theorem tactics
and theorems to tactics.
In other words, a theorem tactic takes a theorem and does something
to the current goal using that theorem.
A theorem tactical takes a theorem tactic and a theorem and does something
to the current goal. Typically, it will preprocess the theorem somehow
before handing the result to the theorem tactic. (In fact, the
tactical may apply the theorem tactic multiple times, sequentially
or in parallel (in different subgoals).)
The functions in this section manipulate theorem tacticals.
I will write out pseudo-definitions of these functions that pretend
that a theorem tactical is a function from theorems to theorems which
happens to side-effect the goal; remember that the actual type is
very different than this.
(thtc1 THEN_TCL thtc2) tht th
= tht (thtc1 (thtc2 th))
(thtc1 ORELSE_TCL thtc2) tht th
= (tht (thtc1 th)) ORELSE (tht (thtc2 th))
ALL_THEN = I
(all_then is the theorem tactical which does nothing to the theorem
before handing it to the theorem tactic)
NO_THEN
theorem tactical which always fails
REPEAT_TCL thtc
= (thtc THEN_TCL (REPEAT_TCL thtc)) ORELSE_TCL ALL_THEN
REPEAT_GTCL ???
I don't understand why REPEAT_GTCL is different than REPEAT_TCL.
Fortunately, REPEAT_GTCL is never used, so it can't be very important :-)
EVERY_TCL [thtc1;...;thtcn] = thtc1 THEN_TCL ... THEN_TCL thtcn
FIRST_TCL [thtc1;...;thtcn] = thtc1 ORELSE_TCL ... ORELSE_TCL thtcn
LABEL_TAC s th
Adds th as a new assumption, with label s. (Assumes that any hypotheses
of th are also hypotheses of the goal.)
ASSUME_TAC = LABEL_TAC ""
USE_ASSUM s tht
Find the first assumption with label s (call this assumption th).
Applies tactic (tht th).
FIND_ASSUM tht tm
Find the first assumption whose conclusion is equal (not alpha-equivalent!)
to tm (call this assumption th). Applies tactic (tht th).
POP_ASSUM tht
Call the first (most recently added) assumption th. Removes th
from assumption list, and applies tactic (tht th).
ASSUM_LIST thlt
Applies tactic (thlt thl), where thl is the list of assumptions.
POP_ASSUM_LIST thlt
Applies tactic (thlt thl) after removing all assumptions, where thl
is the list of assumptions.
EVERY_ASSUM tht = ASSUM_LIST (MAP_EVERY tht)
(* This is not the actual definition; I think it is equivalent. *)
FIRST_ASSUM tht = ASSUM_LIST (MAP_FIRST tht)
RULE_ASSUM_TAC thth
Replaces every assumption with thth applied to that assumption.
ASM thlt thl
Applies tactic (thlt (asm @ thl)), where asm is the list of assumptions.
ACCEPT_TAC th
A tactic which solves the current goal, assuming the conclusion of th
is alpha-equivalent to the goal.
CONV_TAC c
Create tactic from a conversion. This allows the conversion to return
|- p rather than |- p = T on a term "p". It also eliminates any goals of
the form "T" automatically.
REFL_TAC
Accepts if the current goal is of the form `a = a`.
ABS_TAC
Converts goal `(\x. a) = (\x. b)` to `a = b`.
MK_COMB_TAC
Converts goal `f a = g b` to `f = g` and `a = b`.
AP_TERM_TAC
Converts goal `f a = f b` to `a = b`.
AP_THM_TAC
Converts goal `f a = g a` to `f = g`.
BINOP_TAC
Converts goal `f a b = f c d` to `a = c` and `b = d`.
SUBST1_TAC `|- a = b`
Converts goal `P[a]` to `P[b]`
SUBST_ALL_TAC `|- a = b`
Rewrites `a` to `b` in goal and all assumptions.
BETA_TAC
Does all possible beta-reductions in goal.
DISCH_TAC
Converts goal `a ==> b` to `b` and adds `a` as a new assumption.
(Treats goal `~a` as `a ==> F`.)
MP_TAC `|- a`
Converts goal `b` to `a ==> b`.
EQ_TAC
Converts goal `(a:bool) = b` to `a ==> b` and `b ==> a`.
UNDISCH_TAC `a`
Finds an assumption with a conclusion alpha-equivalent to `a`.
Removes this assumption, and converts goal `b` to `a ==> b`.
SPEC_TAC (`x`,`a`)
Converts goal `P[a]` to `!x. P[x]`
X_GEN_TAC `x`
Converts goal `!y. P[y]` to `P[x]`
GEN_TAC
Converts goal `!x. P[x]` to `P[x]`
EXISTS_TAC `a`
Converts goal `?x. P[x]` to `P[a]`
X_CHOOSE_TAC `x` `|- ?y. P[y]`
Adds a new assumption `P[x]`
CHOOSE_TAC `|- ?x. P[x]`
Adds a new assumption `P[x]`
CONJ_TAC
Converts goal `a /\ b` to `a` and `b`
DISJ1_TAC
Converts goal `a \/ b` to `a`
DISJ2_TAC
Converts goal `a \/ b` to `b`
DISJ_CASES_TAC `|- a \/ b`
Creates two subgoals. Adds assumption `a` in one subgoal, `b` in the other.
CONTR_TAC `|- F`
Accepts the goal.
MATCH_ACCEPT_TAC `|- a`
First applies (REPEAT GEN_TAC), then accepts if the conclusion is an
instance of `a`
MATCH_MP_TAC `|- a ==> b`
Converts a goal `b@` into `a@`.
CONJUNCTS_THEN2 tht1 tht2 `|- a /\ b`
Applies tactic (tht1 `|- a`) THEN (tht2 `|- b`)
CONJUNCTS_THEN tht `|- a /\ b`
Applies tactic (tht `|- a`) THEN (tht `|- b`)
DISJ_CASES_THEN2 tht1 tht2 `|- a \/ b`
Generates two subgoals. Applies (tht1 `|- a`) in one subgoal,
(tht2 `|- b`) in the other.
DISJ_CASES_THEN tht `|- a \/ b`
Generates two subgoals. Applies (tht `|- a`) in one subgoal,
(tht `|- b`) in the other.
DISCH_THEN tht
Converts goal `a ==> b` to `b`, then applies tactic (tht `|- a`).
(Treats `~a` as `a ==> F`)
X_CHOOSE_THEN `x` tht `|- ?y. P[y]`
Applies tactic (tht `|- P[x]`)
CHOOSE_THEN tht `|- ?x. P[x]`
Applies tactic (tht `|- P[x]`)
STRIP_THM_THEN = FIRST_TCL [CONJUNCTS_THEN; DISJ_CASES_THEN; CHOOSE_THEN]
(That is, it acts like CONJUNCTS_THEN, DISJ_CASES_THEN, or CHOOSE_THEN,
depending on whether the theorem is a conjunction, disjunction, or
exists.)
ANTE_RES_THEN tht `|- a@`
For every assumption `|- a ==> b`, applies tactic (tht `|- b@`)
IMP_RES_THEN tht `|- a ==> b`
For every assumption `|- a@`, applies tactic (tht `|- b@`)
STRIP_ASSUME_TAC th
Starts with (REPEAT_TCL STRIP_THM_THEN) applied to th.
Call the resulting theorem(s) gth. If gth is `F`, or equal to the
goal, then solve the goal; if gth is already an assumption, do nothing;
otherwise, add gth as an assumption.
STRUCT_CASES_TAC th
Starts with (REPEAT_TCL STRIP_THM_THEN) applied to th.
Call the resulting theorem(s) gth. If gth is an equality, then use
it to rewrite the goal; otherwise, add gth as an assumption.
STRIP_GOAL_THEN tht
= FIRST [GEN_TAC; CONJ_TAC; DISCH_THEN tht]
(If the current goal is a forall, then generalize; if it is a conjunction,
prove the two cases separately; if it is an implication `a ==> b` then
convert to `b` and apply (tht `a`).)
STRIP_TAC = STRIP_GOAL_THEN STRIP_ASSUME_TAC
ABBREV_TAC `x = a`
Rewrites `a` to `x` in the goal and all assumptions, then adds `a = x`
as a new assumption.
EXPAND_TAC `x`
Finds the first assumption of the form `a = x`, rewrites `x` to `a` in
the goal, and beta-reduces the goal.
UNDISCH_THEN `a` tht
Finds an assumption `|- a`, removes the assumption, and applies the
tactic (tht `|- a`)
FIRST_X_ASSUM tht
Like FIRST_ASSUM, but removes the assumption successfully used by the
tactic.
SUBGOAL_THEN `a` tht
Creates two subgoals. In the first, changes the goal to `a`.
In the second, applies tactic (tht `|- a`).
FREEZE_THEN tht `|- a`
Applies tactic (tht `|- a`) (while "freezing variables"? Does this have
something to do with metavariables? I don't understand this...) (???)
X_META_EXISTS_TAC `x`
Converts goal `?y. P[y]` to `P[x]`, where `x` is a metavariable.
META_EXISTS_TAC
Converts goal `?x. P[x]` to `P[x]`, where `x` is a metavariable.
META_SPEC_TAC `x` `!y. P[y]` adds a new assumption `P[x]`, where
`x` is a metavariable.
CHEAT_TAC
Introduce the goal as a new axiom, then solve the goal.
RECALL_ACCEPT_TAC f x = ACCEPT_TAC (f x)
As a side-effect, prints out the time taken to compute (f x); delays
this computation until it is required.
ANTS_TAC
Converts goal `(p ==> q) ==> r` to `p` and `q ==> r`
itab:
ITAUT_TAC
Intuitionistic theorem prover: understands
and,forall,implies,not,iff (boolean equality),or,exists,T,F;
applies a long list of rules dealing with the above types of terms
until it runs out of rules to apply or proves the theorem.
Either succeeds or leaves the goal state unchanged.
ITAUT `a` gives `|-a` if ITAUT can prove it.
CONTRAPOS `|- a ==> b` gives `|- ~b ==> ~a`
simp:
REWR_CONV `|- a = b`
A conversion which rewrites `a@` to `b@`
A conditional rewrite is a conversion which produces a theorem
of the form `|- P ==> (a = b)`. This rewrites `a` to `b` under
the condition `P`. Previous conversionals cannot deal with conditional
rewrites.
IMP_REWR_CONV `|- P ==> (a = b)`
A conversion which rewrites `a@` to `b@` under the condition `P@`.
ORDERED_REWR_CONV ord `|- a = b`
A conversion which rewrites `a@` to `b@` if (ord `a@` `b@`)
(otherwise it fails)
ORDERED_IMP_REWR_CONV ord `|- P ==> (a = b)`
A conversion which rewrites `a@` to `b@` under the condition `P@`
if (ord `a@` `b@`)
term_order
An ordering function which is AC-compatible for any binary operator.
net_of_thm rep `|- P ==> (a = b)` (or `|- a = b`) net
Adds a component to net which matches a term and returns a
conversion rewriting that term.
If rep is true and `a` appears in `b`, then it rewrites `(a = b)` to `T`.
If rep is true and the rewrite is permutative, then it uses an
ordered rewrite to rewrite `a` to `b`.
If neither of the above is true, then it uses an ordinary rewrite.
Conditional rewrites are entered as level 3; unconditional as level 1.
net_of_conv tm conv net
Adds a component to net which matches tm and returns conv. Entered as level 2.
net_of_cong th net
Adds a component to net for a congruence rule. (This is a rule of the
form `P1 ==> (P2 ==> (...(Pn ==> (a = b))))` ). Entered at level 4.
mk_rewrites cf th rew_list
Prepends rewrites for th to new_list
I will describe the action in terms of a notional
add_rew function.
(add_rew l `|- !x. P[x]`) --> (add_rew l `|- P[x]`)
(add_rew l `|- P1 /\ P2`) --> (add_rew l `|- P1`), (add_rew l `|- P2`)
if cf, then (add_rew l `|- P1 ==> P2`) --> (add_rew (`P1`::l) `|- P2`)
(add_rew l `|- a = b`) adds a conditional rewrite with conditions l
(if l is empty, this is an unconditional rewrite;
if cf is false, then l is always empty)
(add_rew l `|- ~(a = b)`) --> (add_rew l `|- (a = b) = F`), (add_rew l `|- (b = a) = F`)
(add_rew l `|- ~a`) --> (add_rew l `|- a = F`)
If none of the above hold, (add_rew l `|- a`) --> (add_rew l `|- a = T`)
REWRITES_CONV net `a`
Looks up `a` in the net, and applies the resulting conversion to `a`.
There's a lot of generality in the simpset data structure which is not
used; I'm not going to try to understand the general-purpose operation,
but only the portions of it which are actually used in HOL Light.
Of the four fields in the simpset data structure, only the first ever
changes: the second is always basic_prover, the third is always the
empty list, and the fourth is always (mk_rewrites true).
The first field is a conversion net.
basic_prover strat ss lev `a`
Tries to prove `|- a`. Succeeds if `a` = `T`, or if
(strat ss lev `a`) proves `|- a = T`.
(* None of the following are ever called.
ss_of_thms thms ss
Augments a simpset with a list of theorems (using the rewrite maker
from the simpset to add the theorems to the conversion net).
ss_of_conv keytm conv ss
Augments a simpset with a conversion (using (net_of_conv keytm conv)
to add the conversion to the conversion net).
ss_of_prover newprover ss
Replaces the prover in the simpset with newprover.
ss_of_provers newprovers ss
Prepends newprovers to the list of subprovers in the simpset.
ss_of_maker newmaker ss
Replaces the rewrite maker in the simpset with newmaker.
*)
AUGMENT_SIMPSET th ss
Uses the rewrite maker from the simpset (always (mk_rewrites true))
to create a list of rewrite theorems from th; use (net_of_thm true)
to add these theorems to the conversion net in the simpset.
Note: IMP_REWRITES_CONV and GEN_SUB_CONV have a different signature than
what I am documenting; if you ever want to call them directly,
look at the source. I will first describe the meaning of these functions;
then I will describe their implementation.
(IMP_REWRITES_CONV strat ss lev) is a conversion which looks up the
term in the ss conversion net. It tries unconditional rewrites before
conditional rewrites. It will only accept a conditional rewrite if
(strat ss (lev-1)) can rewrite the condition to `T`.
(GEN_SUB_CONV strat ss lev) rewrites combinations and abstractions
in a depth-first manner by calling (strat ss lev) on subterms. It
has special handling for if-then-else and implications; it adds
the condition to the simpset before simplifying the rest of the expression.
Both of these functions fail if they perform no rewrites.
IMP_REWRITES_CONV strat ss lev
Try to find a conversion for tm at level < 4 (i.e., not a
congruence rule) which is either unconditional or (if lev > 0) such that
the condition can be rewritten to `T` by (strat ss (lev-1)).
RUN_SUB_CONV -- called only by GEN_SUB_CONV; not documented.
GEN_SUB_CONV strat ss lev
Try to find a congruence rule for tm (i.e., a rule at level 4).
The conclusion of a congruence rule is of the form
`A[x1,...,xn] = A[x1',...,xn']`, so tm must be of the form `A[a1,...,an]`.
Each hypothesis of a congruence rule is either of the form
`xi = xi'` or `P[x1',...,x(i-1)'] ==> (xi = xi')`.
In the former case, use (strat ss lev) to rewrite `a1` to `a1'`;
in the latter case, use AUGMENT_SIMPSET to add
`P[a1',...,a(i-1)']` to ss (getting ss') and use (strat ss' lev) for
the rewrite.
Combine all of these rewrites to rewrite `A[a1,...,an]` to
`A[a1',...,an']`.
If this fails, then if tm is `f a`, then use (strat ss lev) to
rewrite `f` to `g` and `a` to `b` and return `|- f a = g b`.
If tm is `\x. a[x]`, then use (strat ss lev) to rewrite `a[x]` to `b[x]`
and return `|- (\x. a[x]) = (\x. b[x])`.
Throughout GEN_SUB_CONV (in both the congruence rule case, and the combination
case), if the call to strat fails to rewrite `a`, then it rewrites
`a` to `a`; but if all the calls to strat fail (so that GEN_SUB_CONV
would rewrite tm to tm), GEN_SUB_CONV fails instead.
Note that there are only two congruence rules used in HOL Light: one for
rewriting `if g then t else e` and one for rewriting `p ==> q`.
ONCE_DEPTH_SQCONV ss lev
= (IMP_REWRITES_CONV ONCE_DEPTH_SQCONV ss lev) ORELSEC
(GEN_SUB_CONV ONCE_DEPTH_SQCONF ss lev)
DEPTH_SQCONV ss lev
= THENQC (GEN_SUB_CONV DEPTH_SQCONV ss lev)
(IMP_REWRITES_CONV DEPTH_SQCONV ss lev)
REDEPTH_SQCONV ss lev
= REPEATQC (DEPTH_CONV ss lev)
TOP_DEPTH_SQCONV ss lev
= REPEATQC ((IMP_REWRITES_CONV TOP_DEPTH_SQCONV ss lev) ORELSEC
(GEN_SUB_CONV TOP_DEPTH_SQCONV ss lev))
TOP_SWEEP_SQCONV ss lev
= THENQC (REPEATC (IMP_REWRITES_CONV TOP_SWEEP_SQCONV ss lev))
(GEN_SUB_CONV TOP_SWEEP_SQCONV ss lev)
Basic rewrites:
There is a global set of "basic rewrites". These are canonicalized with
(mk_rewrites false) (so there is no handling of conditional rewrites),
and added to a basic conversion net.
set_basic_rewrites thl: sets the "basic rewrite" set to thl
extend_basic_rewrites thl: adds thl to the "basic rewrite" set
basic_rewrites (): retrieves the (canonicalized) "basic rewrite" set
basic_net (): retrieves the conversion net for the "basic rewrite" set
There is also a set of basic congruences; since HOL has only two congruence
rules, I won't bother documenting set_basic_congs, extend_basic_congs,
basic_congs.
GENERAL_REWRITE_CONV rep cnvl net thl
Canonicalizes thl with (mk_rewrites false), adds these conversions
to net with (net_of_thm rep) (giving final_net), and then rewrites with
(cnvl (REWRITES_CONV final_net)).
GEN_REWRITE_CONV cnvl thl
= GENERAL_REWRITE_CONV false cnvl empty_net thl
PURE_REWRITE_CONV thl
= GENERAL_REWRITE_CONV true TOP_DEPTH_CONV empty_net thl
REWRITE_CONV thl
= GENERAL_REWRITE_CONV true TOP_DEPTH_CONV (basic_net()) thl
PURE_ONCE_REWRITE_CONV thl
= GENERAL_REWRITE_CONV false ONCE_DEPTH_CONV empty_net thl
ONCE_REWRITE_CONV thl
= GENERAL_REWRITE_CONV false ONCE_DEPTH_CONV (basic_net()) thl
LIMITED_REWRITE_CONV n thl
Rewrite n times with
(GEN_REWRITE_CONV ONCE_DEPTH_CONV ths THENC
GENERAL_REWRITE_CONV true TOP_DEPTH_CONV (basic_net()) [])
GEN_REWRITE_RULE cnvl thl
= CONV_RULE(GEN_REWRITE_CONV cnvl thl)
PURE_REWRITE_RULE thl
= CONV_RULE(PURE_REWRITE_CONV thl)
REWRITE_RULE thl
= CONV_RULE(REWRITE_CONV thl)
PURE_ONCE_REWRITE_RULE thl
= CONV_RULE(PURE_ONCE_REWRITE_CONV thl)
ONCE_REWRITE_RULE thl
= CONV_RULE(ONCE_REWRITE_CONV thl)
PURE_ASM_REWRITE_RULE, ASM_REWRITE_RULE,
PURE_ONCE_ASM_REWRITE_RULE, ONCE_ASM_REWRITE_RULE
As non-"ASM_", but adds theorem hypotheses to the rewrite list.
GEN_REWRITE_TAC, PURE_REWRITE_TAC, REWRITE_TAC,
PURE_ONCE_REWRITE_TAC, ONCE_REWRITE_TAC
As "_RULE", but use CONV_TAC instead of CONV_RULE.
PURE_ASM_REWRITE_TAC, ASM_REWRITE_TAC,
PURE_ONCE_ASM_REWRITE_TAC, ONCE_ASM_REWRITE_TAC
As non-"ASM_", but adds current assumptions to the rewrite list.
GEN_SIMPLIFY_CONV strat ss lev thl
Use AUGMENT_SIMPSET to add thl to ss (giving ss'); then do
TRY_CONV (strat ss' lev)
ONCE_SIMPLIFY_CONV ss
= GEN_SIMPLIFY_CONV ONCE_DEPTH_SQCONV ss 1
SIMPLIFY_CONV ss
= GEN_SIMPLIFY_CONV TOP_DEPTH_SQCONV ss 3
empty_ss: an empty simpset (no conversions in the conversion net)
basic_ss thl
Canonicalizes thl with (mk_rewrites true), then adds the rewrites
to (basic_net()) with (net_of_thm true). Also adds the basic congruences.
Returns the resulting simpset.
SIMP_CONV
= SIMPLIFY_CONV (basic_ss [])
PURE_SIMP_CONV
= SIMPLIFY_CONV empty_ss
ONCE_SIMP_CONV
= ONCE_SIMPLIFY_CONV (basic_ss []) thl
SIMP_RULE, PURE_SIMP_RULE, ONCE_SIMP_RULE
As "_CONV", but calls CONV_RULE
SIMP_TAC, PURE_SIMP_TAC, ONCE_SIMP_TAC
As "_CONV", but calls CONV_TAC
ASM_SIMP_TAC, PURE_ASM_SIMP_TAC, ONCE_ASM_SIMP_TAC
As non-"ASM_", but adds current assumptions to the rewrite list
theorems:
val ( EQ_REFL ) : thm = |- !x. x = x
val ( EQ_REFL_T ) : thm = |- !x. (x = x) = T
val ( EQ_SYM ) : thm = |- !x y. (x = y) ==> (y = x)
val ( EQ_SYM_EQ ) : thm = |- !x y. (x = y) = y = x
val ( EQ_TRANS ) : thm = |- !x y z. (x = y) /\ (y = z) ==> (x = z)
val ( REFL_CLAUSE ) : thm = |- !x. (x = x) = T
AC thl `a = b`
Returns `|- a = b` or fails; succeeds if ordered rewriting using thl
can rewrite `a = b` to `T` or `c = c`
val ( BETA_THM ) : thm = |- !f y. (\x. f x) y = f y
val ( ABS_SIMP ) : thm = |- !t1 t2. (\x. t1) t2 = t1
val ( CONJ_ASSOC ) : thm = |- !t1 t2 t3. t1 /\ t2 /\ t3 = (t1 /\ t2) /\ t3
val ( CONJ_SYM ) : thm = |- !t1 t2. t1 /\ t2 = t2 /\ t1
val ( CONJ_ACI ) : thm =
|- (p /\ q = q /\ p) /\
((p /\ q) /\ r = p /\ q /\ r) /\
(p /\ q /\ r = q /\ p /\ r) /\
(p /\ p = p) /\
(p /\ p /\ q = p /\ q)
val ( DISJ_ASSOC ) : thm = |- !t1 t2 t3. t1 \/ t2 \/ t3 = (t1 \/ t2) \/ t3
val ( DISJ_SYM ) : thm = |- !t1 t2. t1 \/ t2 = t2 \/ t1
val ( DISJ_ACI ) : thm =
|- (p \/ q = q \/ p) /\
((p \/ q) \/ r = p \/ q \/ r) /\
(p \/ q \/ r = q \/ p \/ r) /\
(p \/ p = p) /\
(p \/ p \/ q = p \/ q)
val ( FORALL_SIMP ) : thm = |- !t. (!x. t) = t
val ( EXISTS_SIMP ) : thm = |- !t. (?x. t) = t
val ( EQ_CLAUSES ) : thm =
|- !t. ((T = t) = t) /\ ((t = T) = t) /\ ((F = t) = ~t) /\ ((t = F) = ~t)
val ( NOT_CLAUSES_WEAK ) : thm = |- (~T = F) /\ (~F = T)
val ( AND_CLAUSES ) : thm =
|- !t. (T /\ t = t) /\
(t /\ T = t) /\
(F /\ t = F) /\
(t /\ F = F) /\
(t /\ t = t)
val ( OR_CLAUSES ) : thm =
|- !t. (T \/ t = T) /\
(t \/ T = T) /\
(F \/ t = t) /\
(t \/ F = t) /\
(t \/ t = t)
val ( IMP_CLAUSES ) : thm =
|- !t. (T ==> t = t) /\
(t ==> T = T) /\
(F ==> t = T) /\
(t ==> t = T) /\
(t ==> F = ~t)
REFL_CLAUSE, EQ_CLAUSES, NOT_CLAUSES_WEAK, AND_CLAUSES, OR_CLAUSES,
IMP_CLAUSES, FORALL_SIMP, EXISTS_SIMP, BETA_THM, and `((x = x) ==> p) = p`
are all "basic rewrites".
val ( EXISTS_UNIQUE_THM ) : thm =
|- !P. (?!x. P x) = (?x. P x) /\ (!x x'. P x /\ P x' ==> (x = x'))
val ( EXISTS_REFL ) : thm = |- !a. ?x. x = a
val ( EXISTS_UNIQUE_REFL ) : thm = |- !a. ?!x. x = a
val ( EXISTS_UNIQUE_ALT ) : thm = |- !P. (?!x. P x) = (?x. !y. P y = x = y)
val ( UNWIND_THM1 ) : thm = |- !P a. (?x. (a = x) /\ P x) = P a
val ( UNWIND_THM2 ) : thm = |- !P a. (?x. (x = a) /\ P x) = P a
val ( SWAP_FORALL_THM ) : thm = |- !P. (!x y. P x y) = (!y x. P x y)
val ( SWAP_EXISTS_THM ) : thm = |- !P. (?x y. P x y) = (?y x. P x y)
val ( FORALL_AND_THM ) : thm =
|- !P Q. (!x. P x /\ Q x) = (!x. P x) /\ (!x. Q x)
val ( AND_FORALL_THM ) : thm =
|- !P Q. (!x. P x) /\ (!x. Q x) = (!x. P x /\ Q x)
val ( LEFT_AND_FORALL_THM ) : thm = |- !P Q. (!x. P x) /\ Q = (!x. P x /\ Q)
val ( RIGHT_AND_FORALL_THM ) : thm = |- !P Q. P /\ (!x. Q x) = (!x. P /\ Q x)
val ( EXISTS_OR_THM ) : thm =
|- !P Q. (?x. P x \/ Q x) = (?x. P x) \/ (?x. Q x)
val ( OR_EXISTS_THM ) : thm =
|- !P Q. (?x. P x) \/ (?x. Q x) = (?x. P x \/ Q x)
val ( LEFT_OR_EXISTS_THM ) : thm = |- !P Q. (?x. P x) \/ Q = (?x. P x \/ Q)
val ( RIGHT_OR_EXISTS_THM ) : thm = |- !P Q. P \/ (?x. Q x) = (?x. P \/ Q x)
val ( LEFT_EXISTS_AND_THM ) : thm = |- !P Q. (?x. P x /\ Q) = (?x. P x) /\ Q
val ( RIGHT_EXISTS_AND_THM ) : thm = |- !P Q. (?x. P /\ Q x) = P /\ (?x. Q x)
val ( TRIV_EXISTS_AND_THM ) : thm =
|- !P Q. (?x. P /\ Q) = (?x. P) /\ (?x. Q)
val ( LEFT_AND_EXISTS_THM ) : thm = |- !P Q. (?x. P x) /\ Q = (?x. P x /\ Q)
val ( RIGHT_AND_EXISTS_THM ) : thm = |- !P Q. P /\ (?x. Q x) = (?x. P /\ Q x)
val ( TRIV_AND_EXISTS_THM ) : thm =
|- !P Q. (?x. P) /\ (?x. Q) = (?x. P /\ Q)
val ( TRIV_FORALL_OR_THM ) : thm = |- !P Q. (!x. P \/ Q) = (!x. P) \/ (!x. Q)
val ( TRIV_OR_FORALL_THM ) : thm = |- !P Q. (!x. P) \/ (!x. Q) = (!x. P \/ Q)
val ( RIGHT_IMP_FORALL_THM ) : thm =
|- !P Q. P ==> (!x. Q x) = (!x. P ==> Q x)
val ( RIGHT_FORALL_IMP_THM ) : thm =
|- !P Q. (!x. P ==> Q x) = P ==> (!x. Q x)
val ( LEFT_IMP_EXISTS_THM ) : thm =
|- !P Q. (?x. P x) ==> Q = (!x. P x ==> Q)
val ( LEFT_FORALL_IMP_THM ) : thm =
|- !P Q. (!x. P x ==> Q) = (?x. P x) ==> Q
val ( TRIV_FORALL_IMP_THM ) : thm =
|- !P Q. (!x. P ==> Q) = (?x. P) ==> (!x. Q)
val ( TRIV_EXISTS_IMP_THM ) : thm =
|- !P Q. (?x. P ==> Q) = (!x. P) ==> (?x. Q)
ind-defs:
RIGHT_BETAS [`x`;`y`] `|- f = \x y. A[x,y]` gives
`|- f x y = A[x,y]`
HALF_BETA_EXPAND [`x`;`y`] `|- f = \x y. A[x,y]` gives
`|- !x y. f x y = A[x,y]`
SIMPLE_DISJ_PAIR `P \/ Q |- R` gives
(`P |- R`, `Q |- R`)
FORALL_IMPS_CONV
Rewrites `!x y. P[x,y] ==> Q` to `(?x y. P[x,y]) ==> Q`
AND_IMPS_CONV
Rewrites:
(* (!x1..xn. P1[xs] ==> Q[xs]) /\ ... /\ (!x1..xn. Pm[xs] ==> Q[xs]) *)
(* -> (!x1..xn. P1[xs] \/ ... \/ Pm[xs] ==> Q[xs]) *)
EXISTS_EQUATION `x = a` `ASM,x = a |- P[x]`
gives `ASM |- ?x. P[x]`
val ( MONO_AND ) : thm = |- (A ==> B) /\ (C ==> D) ==> A /\ C ==> B /\ D
val ( MONO_OR ) : thm = |- (A ==> B) /\ (C ==> D) ==> A \/ C ==> B \/ D
val ( MONO_IMP ) : thm = |- (B ==> A) /\ (C ==> D) ==> (A ==> C) ==> B ==> D
val ( MONO_NOT ) : thm = |- (B ==> A) ==> ~A ==> ~B
val ( MONO_FORALL ) : thm = |- (!x. P x ==> Q x) ==> (!x. P x) ==> (!x. Q x)
val ( MONO_EXISTS ) : thm = |- (!x. P x ==> Q x) ==> (?x. P x) ==> (?x. Q x)
BACKCHAIN_TAC:
"Simplified version of MATCH_MP_TAC to avoid quantifier troubles."
MONO_ABS_TAC:
(* ?- (\x. P[x]) x1 .. xn ==> (\y. Q[y]) x1 .. xn *)
(* ================================================== *)
(* ?- !x1. P[x1] x2 .. xn ==> Q[x1] x2 .. xn *)
mono_tactics:
A global variable holding a set of tactics for proving monotonicity.
APPLY_MONOTAC
Prove `a ==> a` automatically; otherwise, select a tactic from
mono_tactics and apply it.
MONO_STEP_TAC
= REPEAT GEN_TAC THEN APPLY_MONOTAC
MONO_TAC
= REPEAT MONO_STEP_TAC THEN ASM_REWRITE_TAC[]
class:
This is an axiom:
val ( ETA_AX ) : thm = |- !t. (\x. t x) = t
ETA_CONV
Rewrites `(\x. f x)` to `f`
val ( EQ_EXT ) : thm = |- !f g. (!x. f x = g x) ==> (f = g)
val ( FUN_EQ_THM ) : thm = |- !f g. (f = g) = (!x. f x = g x)
EXT `|- (!x. f x = g x)` gives `|- f = x`
This is an axiom: