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 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444
|
(** * Logic: Logic in Coq *)
Set Warnings "-notation-overridden,-parsing".
Require Export Tactics.
(** In previous chapters, we have seen many examples of factual
claims (_propositions_) and ways of presenting evidence of their
truth (_proofs_). In particular, we have worked extensively with
_equality propositions_ of the form [e1 = e2], with
implications ([P -> Q]), and with quantified propositions ([forall
x, P]). In this chapter, we will see how Coq can be used to carry
out other familiar forms of logical reasoning.
Before diving into details, let's talk a bit about the status of
mathematical statements in Coq. Recall that Coq is a _typed_
language, which means that every sensible expression in its world
has an associated type. Logical claims are no exception: any
statement we might try to prove in Coq has a type, namely [Prop],
the type of _propositions_. We can see this with the [Check]
command: *)
Check 3 = 3.
(* ===> Prop *)
Check forall n m : nat, n + m = m + n.
(* ===> Prop *)
(** Note that _all_ syntactically well-formed propositions have type
[Prop] in Coq, regardless of whether they are true or not.
Simply _being_ a proposition is one thing; being _provable_ is
something else! *)
Check forall n : nat, n = 2.
(* ===> Prop *)
Check 3 = 4.
(* ===> Prop *)
(** Indeed, propositions don't just have types: they are _first-class
objects_ that can be manipulated in the same ways as the other
entities in Coq's world. So far, we've seen one primary place
that propositions can appear: in [Theorem] (and [Lemma] and
[Example]) declarations. *)
Theorem plus_2_2_is_4 :
2 + 2 = 4.
Proof. reflexivity. Qed.
(** But propositions can be used in many other ways. For example, we
can give a name to a proposition using a [Definition], just as we
have given names to expressions of other sorts. *)
Definition plus_fact : Prop := 2 + 2 = 4.
Check plus_fact.
(* ===> plus_fact : Prop *)
(** We can later use this name in any situation where a proposition is
expected -- for example, as the claim in a [Theorem] declaration. *)
Theorem plus_fact_is_true :
plus_fact.
Proof. reflexivity. Qed.
(** We can also write _parameterized_ propositions -- that is,
functions that take arguments of some type and return a
proposition. *)
(** For instance, the following function takes a number
and returns a proposition asserting that this number is equal to
three: *)
Definition is_three (n : nat) : Prop :=
n = 3.
Check is_three.
(* ===> nat -> Prop *)
(** In Coq, functions that return propositions are said to define
_properties_ of their arguments.
For instance, here's a (polymorphic) property defining the
familiar notion of an _injective function_. *)
Definition injective {A B} (f : A -> B) :=
forall x y : A, f x = f y -> x = y.
Lemma succ_inj : injective S.
Proof.
intros n m H. inversion H. reflexivity.
Qed.
(** The equality operator [=] is also a function that returns a
[Prop].
The expression [n = m] is syntactic sugar for [eq n m], defined
using Coq's [Notation] mechanism. Because [eq] can be used with
elements of any type, it is also polymorphic: *)
Check @eq.
(* ===> forall A : Type, A -> A -> Prop *)
(** (Notice that we wrote [@eq] instead of [eq]: The type
argument [A] to [eq] is declared as implicit, so we need to turn
off implicit arguments to see the full type of [eq].) *)
(* ################################################################# *)
(** * Logical Connectives *)
(* ================================================================= *)
(** ** Conjunction *)
(** The _conjunction_ (or _logical and_) of propositions [A] and [B]
is written [A /\ B], representing the claim that both [A] and [B]
are true. *)
Example and_example : 3 + 4 = 7 /\ 2 * 2 = 4.
(** To prove a conjunction, use the [split] tactic. It will generate
two subgoals, one for each part of the statement: *)
Proof.
(* WORKED IN CLASS *)
split.
- (* 3 + 4 = 7 *) reflexivity.
- (* 2 + 2 = 4 *) reflexivity.
Qed.
(** For any propositions [A] and [B], if we assume that [A] is true
and we assume that [B] is true, we can conclude that [A /\ B] is
also true. *)
Lemma and_intro : forall A B : Prop, A -> B -> A /\ B.
Proof.
intros A B HA HB. split.
- apply HA.
- apply HB.
Qed.
(** Since applying a theorem with hypotheses to some goal has the
effect of generating as many subgoals as there are hypotheses for
that theorem, we can apply [and_intro] to achieve the same effect
as [split]. *)
Example and_example' : 3 + 4 = 7 /\ 2 * 2 = 4.
Proof.
apply and_intro.
- (* 3 + 4 = 7 *) reflexivity.
- (* 2 + 2 = 4 *) reflexivity.
Qed.
(** **** Exercise: 2 stars (and_exercise) *)
Example and_exercise :
forall n m : nat, n + m = 0 -> n = 0 /\ m = 0.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** So much for proving conjunctive statements. To go in the other
direction -- i.e., to _use_ a conjunctive hypothesis to help prove
something else -- we employ the [destruct] tactic.
If the proof context contains a hypothesis [H] of the form
[A /\ B], writing [destruct H as [HA HB]] will remove [H] from the
context and add two new hypotheses: [HA], stating that [A] is
true, and [HB], stating that [B] is true. *)
Lemma and_example2 :
forall n m : nat, n = 0 /\ m = 0 -> n + m = 0.
Proof.
(* WORKED IN CLASS *)
intros n m H.
destruct H as [Hn Hm].
rewrite Hn. rewrite Hm.
reflexivity.
Qed.
(** As usual, we can also destruct [H] right when we introduce it,
instead of introducing and then destructing it: *)
Lemma and_example2' :
forall n m : nat, n = 0 /\ m = 0 -> n + m = 0.
Proof.
intros n m [Hn Hm].
rewrite Hn. rewrite Hm.
reflexivity.
Qed.
(** You may wonder why we bothered packing the two hypotheses [n = 0]
and [m = 0] into a single conjunction, since we could have also
stated the theorem with two separate premises: *)
Lemma and_example2'' :
forall n m : nat, n = 0 -> m = 0 -> n + m = 0.
Proof.
intros n m Hn Hm.
rewrite Hn. rewrite Hm.
reflexivity.
Qed.
(** For this theorem, both formulations are fine. But it's important
to understand how to work with conjunctive hypotheses because
conjunctions often arise from intermediate steps in proofs,
especially in bigger developments. Here's a simple example: *)
Lemma and_example3 :
forall n m : nat, n + m = 0 -> n * m = 0.
Proof.
intros n m H.
assert (H' : n = 0 /\ m = 0).
{ apply and_exercise. apply H. }
destruct H' as [Hn Hm].
rewrite Hn. reflexivity.
Qed.
(** Another common situation with conjunctions is that we know
[A /\ B] but in some context we need just [A] (or just [B]).
The following lemmas are useful in such cases: *)
Lemma proj1 : forall P Q : Prop,
P /\ Q -> P.
Proof.
intros P Q [HP HQ].
apply HP. Qed.
(** **** Exercise: 1 star, optional (proj2) *)
Lemma proj2 : forall P Q : Prop,
P /\ Q -> Q.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** Finally, we sometimes need to rearrange the order of conjunctions
and/or the grouping of multi-way conjunctions. The following
commutativity and associativity theorems are handy in such
cases. *)
Theorem and_commut : forall P Q : Prop,
P /\ Q -> Q /\ P.
Proof.
(* WORKED IN CLASS *)
intros P Q [HP HQ].
split.
- (* left *) apply HQ.
- (* right *) apply HP. Qed.
(** **** Exercise: 2 stars (and_assoc) *)
(** (In the following proof of associativity, notice how the _nested_
intro pattern breaks the hypothesis [H : P /\ (Q /\ R)] down into
[HP : P], [HQ : Q], and [HR : R]. Finish the proof from
there.) *)
Theorem and_assoc : forall P Q R : Prop,
P /\ (Q /\ R) -> (P /\ Q) /\ R.
Proof.
intros P Q R [HP [HQ HR]].
(* FILL IN HERE *) Admitted.
(** [] *)
(** By the way, the infix notation [/\] is actually just syntactic
sugar for [and A B]. That is, [and] is a Coq operator that takes
two propositions as arguments and yields a proposition. *)
Check and.
(* ===> and : Prop -> Prop -> Prop *)
(* ================================================================= *)
(** ** Disjunction *)
(** Another important connective is the _disjunction_, or _logical or_
of two propositions: [A \/ B] is true when either [A] or [B]
is. (Alternatively, we can write [or A B], where [or : Prop ->
Prop -> Prop].)
To use a disjunctive hypothesis in a proof, we proceed by case
analysis, which, as for [nat] or other data types, can be done
with [destruct] or [intros]. Here is an example: *)
Lemma or_example :
forall n m : nat, n = 0 \/ m = 0 -> n * m = 0.
Proof.
(* This pattern implicitly does case analysis on
[n = 0 \/ m = 0] *)
intros n m [Hn | Hm].
- (* Here, [n = 0] *)
rewrite Hn. reflexivity.
- (* Here, [m = 0] *)
rewrite Hm. rewrite <- mult_n_O.
reflexivity.
Qed.
(** Conversely, to show that a disjunction holds, we need to show that
one of its sides does. This is done via two tactics, [left] and
[right]. As their names imply, the first one requires
proving the left side of the disjunction, while the second
requires proving its right side. Here is a trivial use... *)
Lemma or_intro : forall A B : Prop, A -> A \/ B.
Proof.
intros A B HA.
left.
apply HA.
Qed.
(** ... and a slightly more interesting example requiring both [left]
and [right]: *)
Lemma zero_or_succ :
forall n : nat, n = 0 \/ n = S (pred n).
Proof.
intros [|n].
- left. reflexivity.
- right. reflexivity.
Qed.
(** **** Exercise: 1 star (mult_eq_0) *)
Lemma mult_eq_0 :
forall n m, n * m = 0 -> n = 0 \/ m = 0.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 1 star (or_commut) *)
Theorem or_commut : forall P Q : Prop,
P \/ Q -> Q \/ P.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(* ================================================================= *)
(** ** Falsehood and Negation *)
(** So far, we have mostly been concerned with proving that certain
things are _true_ -- addition is commutative, appending lists is
associative, etc. Of course, we may also be interested in
_negative_ results, showing that certain propositions are _not_
true. In Coq, such negative statements are expressed with the
negation operator [~].
To see how negation works, recall the discussion of the _principle
of explosion_ from the [Tactics] chapter; it asserts that, if we
assume a contradiction, then any other proposition can be derived.
Following this intuition, we could define [~ P] ("not [P]") as
[forall Q, P -> Q]. Coq actually makes a slightly different
choice, defining [~ P] as [P -> False], where [False] is a
_particular_ contradictory proposition defined in the standard
library. *)
Module MyNot.
Definition not (P:Prop) := P -> False.
Notation "~ x" := (not x) : type_scope.
Check not.
(* ===> Prop -> Prop *)
End MyNot.
(** Since [False] is a contradictory proposition, the principle of
explosion also applies to it. If we get [False] into the proof
context, we can [destruct] it to complete any goal: *)
Theorem ex_falso_quodlibet : forall (P:Prop),
False -> P.
Proof.
(* WORKED IN CLASS *)
intros P contra.
destruct contra. Qed.
(** The Latin _ex falso quodlibet_ means, literally, "from falsehood
follows whatever you like"; this is another common name for the
principle of explosion. *)
(** **** Exercise: 2 stars, optional (not_implies_our_not) *)
(** Show that Coq's definition of negation implies the intuitive one
mentioned above: *)
Fact not_implies_our_not : forall (P:Prop),
~ P -> (forall (Q:Prop), P -> Q).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** This is how we use [not] to state that [0] and [1] are different
elements of [nat]: *)
Theorem zero_not_one : ~(0 = 1).
Proof.
intros contra. inversion contra.
Qed.
(** Such inequality statements are frequent enough to warrant a
special notation, [x <> y]: *)
Check (0 <> 1).
(* ===> Prop *)
Theorem zero_not_one' : 0 <> 1.
Proof.
intros H. inversion H.
Qed.
(** It takes a little practice to get used to working with negation in
Coq. Even though you can see perfectly well why a statement
involving negation is true, it can be a little tricky at first to
get things into the right configuration so that Coq can understand
it! Here are proofs of a few familiar facts to get you warmed
up. *)
Theorem not_False :
~ False.
Proof.
unfold not. intros H. destruct H. Qed.
Theorem contradiction_implies_anything : forall P Q : Prop,
(P /\ ~P) -> Q.
Proof.
(* WORKED IN CLASS *)
intros P Q [HP HNA]. unfold not in HNA.
apply HNA in HP. destruct HP. Qed.
Theorem double_neg : forall P : Prop,
P -> ~~P.
Proof.
(* WORKED IN CLASS *)
intros P H. unfold not. intros G. apply G. apply H. Qed.
(** **** Exercise: 2 stars, advanced, recommendedM (double_neg_inf) *)
(** Write an informal proof of [double_neg]:
_Theorem_: [P] implies [~~P], for any proposition [P]. *)
(* FILL IN HERE *)
(** [] *)
(** **** Exercise: 2 stars, recommended (contrapositive) *)
Theorem contrapositive : forall (P Q : Prop),
(P -> Q) -> (~Q -> ~P).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 1 star (not_both_true_and_false) *)
Theorem not_both_true_and_false : forall P : Prop,
~ (P /\ ~P).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 1 star, advancedM (informal_not_PNP) *)
(** Write an informal proof (in English) of the proposition [forall P
: Prop, ~(P /\ ~P)]. *)
(* FILL IN HERE *)
(** [] *)
(** Similarly, since inequality involves a negation, it requires a
little practice to be able to work with it fluently. Here is one
useful trick. If you are trying to prove a goal that is
nonsensical (e.g., the goal state is [false = true]), apply
[ex_falso_quodlibet] to change the goal to [False]. This makes it
easier to use assumptions of the form [~P] that may be available
in the context -- in particular, assumptions of the form
[x<>y]. *)
Theorem not_true_is_false : forall b : bool,
b <> true -> b = false.
Proof.
intros [] H.
- (* b = true *)
unfold not in H.
apply ex_falso_quodlibet.
apply H. reflexivity.
- (* b = false *)
reflexivity.
Qed.
(** Since reasoning with [ex_falso_quodlibet] is quite common, Coq
provides a built-in tactic, [exfalso], for applying it. *)
Theorem not_true_is_false' : forall b : bool,
b <> true -> b = false.
Proof.
intros [] H.
- (* b = false *)
unfold not in H.
exfalso. (* <=== *)
apply H. reflexivity.
- (* b = true *) reflexivity.
Qed.
(* ================================================================= *)
(** ** Truth *)
(** Besides [False], Coq's standard library also defines [True], a
proposition that is trivially true. To prove it, we use the
predefined constant [I : True]: *)
Lemma True_is_true : True.
Proof. apply I. Qed.
(** Unlike [False], which is used extensively, [True] is used quite
rarely, since it is trivial (and therefore uninteresting) to prove
as a goal, and it carries no useful information as a hypothesis.
But it can be quite useful when defining complex [Prop]s using
conditionals or as a parameter to higher-order [Prop]s. We will
see examples of such uses of [True] later on.
*)
(* ================================================================= *)
(** ** Logical Equivalence *)
(** The handy "if and only if" connective, which asserts that two
propositions have the same truth value, is just the conjunction of
two implications. *)
Module MyIff.
Definition iff (P Q : Prop) := (P -> Q) /\ (Q -> P).
Notation "P <-> Q" := (iff P Q)
(at level 95, no associativity)
: type_scope.
End MyIff.
Theorem iff_sym : forall P Q : Prop,
(P <-> Q) -> (Q <-> P).
Proof.
(* WORKED IN CLASS *)
intros P Q [HAB HBA].
split.
- (* -> *) apply HBA.
- (* <- *) apply HAB. Qed.
Lemma not_true_iff_false : forall b,
b <> true <-> b = false.
Proof.
(* WORKED IN CLASS *)
intros b. split.
- (* -> *) apply not_true_is_false.
- (* <- *)
intros H. rewrite H. intros H'. inversion H'.
Qed.
(** **** Exercise: 1 star, optional (iff_properties) *)
(** Using the above proof that [<->] is symmetric ([iff_sym]) as
a guide, prove that it is also reflexive and transitive. *)
Theorem iff_refl : forall P : Prop,
P <-> P.
Proof.
(* FILL IN HERE *) Admitted.
Theorem iff_trans : forall P Q R : Prop,
(P <-> Q) -> (Q <-> R) -> (P <-> R).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 3 stars (or_distributes_over_and) *)
Theorem or_distributes_over_and : forall P Q R : Prop,
P \/ (Q /\ R) <-> (P \/ Q) /\ (P \/ R).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** Some of Coq's tactics treat [iff] statements specially, avoiding
the need for some low-level proof-state manipulation. In
particular, [rewrite] and [reflexivity] can be used with [iff]
statements, not just equalities. To enable this behavior, we need
to import a special Coq library that allows rewriting with other
formulas besides equality: *)
Require Import Coq.Setoids.Setoid.
(** Here is a simple example demonstrating how these tactics work with
[iff]. First, let's prove a couple of basic iff equivalences... *)
Lemma mult_0 : forall n m, n * m = 0 <-> n = 0 \/ m = 0.
Proof.
split.
- apply mult_eq_0.
- apply or_example.
Qed.
Lemma or_assoc :
forall P Q R : Prop, P \/ (Q \/ R) <-> (P \/ Q) \/ R.
Proof.
intros P Q R. split.
- intros [H | [H | H]].
+ left. left. apply H.
+ left. right. apply H.
+ right. apply H.
- intros [[H | H] | H].
+ left. apply H.
+ right. left. apply H.
+ right. right. apply H.
Qed.
(** We can now use these facts with [rewrite] and [reflexivity] to
give smooth proofs of statements involving equivalences. Here is
a ternary version of the previous [mult_0] result: *)
Lemma mult_0_3 :
forall n m p, n * m * p = 0 <-> n = 0 \/ m = 0 \/ p = 0.
Proof.
intros n m p.
rewrite mult_0. rewrite mult_0. rewrite or_assoc.
reflexivity.
Qed.
(** The [apply] tactic can also be used with [<->]. When given an
equivalence as its argument, [apply] tries to guess which side of
the equivalence to use. *)
Lemma apply_iff_example :
forall n m : nat, n * m = 0 -> n = 0 \/ m = 0.
Proof.
intros n m H. apply mult_0. apply H.
Qed.
(* ================================================================= *)
(** ** Existential Quantification *)
(** Another important logical connective is _existential
quantification_. To say that there is some [x] of type [T] such
that some property [P] holds of [x], we write [exists x : T,
P]. As with [forall], the type annotation [: T] can be omitted if
Coq is able to infer from the context what the type of [x] should
be. *)
(** To prove a statement of the form [exists x, P], we must show that
[P] holds for some specific choice of value for [x], known as the
_witness_ of the existential. This is done in two steps: First,
we explicitly tell Coq which witness [t] we have in mind by
invoking the tactic [exists t]. Then we prove that [P] holds after
all occurrences of [x] are replaced by [t]. *)
Lemma four_is_even : exists n : nat, 4 = n + n.
Proof.
exists 2. reflexivity.
Qed.
(** Conversely, if we have an existential hypothesis [exists x, P] in
the context, we can destruct it to obtain a witness [x] and a
hypothesis stating that [P] holds of [x]. *)
Theorem exists_example_2 : forall n,
(exists m, n = 4 + m) ->
(exists o, n = 2 + o).
Proof.
(* WORKED IN CLASS *)
intros n [m Hm]. (* note implicit [destruct] here *)
exists (2 + m).
apply Hm. Qed.
(** **** Exercise: 1 star (dist_not_exists) *)
(** Prove that "[P] holds for all [x]" implies "there is no [x] for
which [P] does not hold." *)
Theorem dist_not_exists : forall (X:Type) (P : X -> Prop),
(forall x, P x) -> ~ (exists x, ~ P x).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 2 stars (dist_exists_or) *)
(** Prove that existential quantification distributes over
disjunction. *)
Theorem dist_exists_or : forall (X:Type) (P Q : X -> Prop),
(exists x, P x \/ Q x) <-> (exists x, P x) \/ (exists x, Q x).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(* ################################################################# *)
(** * Programming with Propositions *)
(** The logical connectives that we have seen provide a rich
vocabulary for defining complex propositions from simpler ones.
To illustrate, let's look at how to express the claim that an
element [x] occurs in a list [l]. Notice that this property has a
simple recursive structure: *)
(** - If [l] is the empty list, then [x] cannot occur on it, so the
property "[x] appears in [l]" is simply false.
- Otherwise, [l] has the form [x' :: l']. In this case, [x]
occurs in [l] if either it is equal to [x'] or it occurs in
[l'].
We can translate this directly into a straightforward recursive
function from taking an element and a list and returning a
proposition: *)
Fixpoint In {A : Type} (x : A) (l : list A) : Prop :=
match l with
| [] => False
| x' :: l' => x' = x \/ In x l'
end.
(** When [In] is applied to a concrete list, it expands into a
concrete sequence of nested disjunctions. *)
Example In_example_1 : In 4 [1; 2; 3; 4; 5].
Proof.
(* WORKED IN CLASS *)
simpl. right. right. right. left. reflexivity.
Qed.
Example In_example_2 :
forall n, In n [2; 4] ->
exists n', n = 2 * n'.
Proof.
(* WORKED IN CLASS *)
simpl.
intros n [H | [H | []]].
- exists 1. rewrite <- H. reflexivity.
- exists 2. rewrite <- H. reflexivity.
Qed.
(** (Notice the use of the empty pattern to discharge the last case
_en passant_.) *)
(** We can also prove more generic, higher-level lemmas about [In].
Note, in the next, how [In] starts out applied to a variable and
only gets expanded when we do case analysis on this variable: *)
Lemma In_map :
forall (A B : Type) (f : A -> B) (l : list A) (x : A),
In x l ->
In (f x) (map f l).
Proof.
intros A B f l x.
induction l as [|x' l' IHl'].
- (* l = nil, contradiction *)
simpl. intros [].
- (* l = x' :: l' *)
simpl. intros [H | H].
+ rewrite H. left. reflexivity.
+ right. apply IHl'. apply H.
Qed.
(** This way of defining propositions recursively, though convenient
in some cases, also has some drawbacks. In particular, it is
subject to Coq's usual restrictions regarding the definition of
recursive functions, e.g., the requirement that they be "obviously
terminating." In the next chapter, we will see how to define
propositions _inductively_, a different technique with its own set
of strengths and limitations. *)
(** **** Exercise: 2 stars (In_map_iff) *)
Lemma In_map_iff :
forall (A B : Type) (f : A -> B) (l : list A) (y : B),
In y (map f l) <->
exists x, f x = y /\ In x l.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 2 stars (in_app_iff) *)
Lemma in_app_iff : forall A l l' (a:A),
In a (l++l') <-> In a l \/ In a l'.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 3 stars (All) *)
(** Recall that functions returning propositions can be seen as
_properties_ of their arguments. For instance, if [P] has type
[nat -> Prop], then [P n] states that property [P] holds of [n].
Drawing inspiration from [In], write a recursive function [All]
stating that some property [P] holds of all elements of a list
[l]. To make sure your definition is correct, prove the [All_In]
lemma below. (Of course, your definition should _not_ just
restate the left-hand side of [All_In].) *)
Fixpoint All {T : Type} (P : T -> Prop) (l : list T) : Prop
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Lemma All_In :
forall T (P : T -> Prop) (l : list T),
(forall x, In x l -> P x) <->
All P l.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 3 stars (combine_odd_even) *)
(** Complete the definition of the [combine_odd_even] function below.
It takes as arguments two properties of numbers, [Podd] and
[Peven], and it should return a property [P] such that [P n] is
equivalent to [Podd n] when [n] is odd and equivalent to [Peven n]
otherwise. *)
Definition combine_odd_even (Podd Peven : nat -> Prop) : nat -> Prop
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
(** To test your definition, prove the following facts: *)
Theorem combine_odd_even_intro :
forall (Podd Peven : nat -> Prop) (n : nat),
(oddb n = true -> Podd n) ->
(oddb n = false -> Peven n) ->
combine_odd_even Podd Peven n.
Proof.
(* FILL IN HERE *) Admitted.
Theorem combine_odd_even_elim_odd :
forall (Podd Peven : nat -> Prop) (n : nat),
combine_odd_even Podd Peven n ->
oddb n = true ->
Podd n.
Proof.
(* FILL IN HERE *) Admitted.
Theorem combine_odd_even_elim_even :
forall (Podd Peven : nat -> Prop) (n : nat),
combine_odd_even Podd Peven n ->
oddb n = false ->
Peven n.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(* ################################################################# *)
(** * Applying Theorems to Arguments *)
(** One feature of Coq that distinguishes it from many other proof
assistants is that it treats _proofs_ as first-class objects.
There is a great deal to be said about this, but it is not
necessary to understand it in detail in order to use Coq. This
section gives just a taste, while a deeper exploration can be
found in the optional chapters [ProofObjects] and
[IndPrinciples]. *)
(** We have seen that we can use the [Check] command to ask Coq to
print the type of an expression. We can also use [Check] to ask
what theorem a particular identifier refers to. *)
Check plus_comm.
(* ===> forall n m : nat, n + m = m + n *)
(** Coq prints the _statement_ of the [plus_comm] theorem in the same
way that it prints the _type_ of any term that we ask it to
[Check]. Why?
The reason is that the identifier [plus_comm] actually refers to a
_proof object_ -- a data structure that represents a logical
derivation establishing of the truth of the statement [forall n m
: nat, n + m = m + n]. The type of this object _is_ the statement
of the theorem that it is a proof of. *)
(** Intuitively, this makes sense because the statement of a theorem
tells us what we can use that theorem for, just as the type of a
computational object tells us what we can do with that object --
e.g., if we have a term of type [nat -> nat -> nat], we can give
it two [nat]s as arguments and get a [nat] back. Similarly, if we
have an object of type [n = m -> n + n = m + m] and we provide it
an "argument" of type [n = m], we can derive [n + n = m + m]. *)
(** Operationally, this analogy goes even further: by applying a
theorem, as if it were a function, to hypotheses with matching
types, we can specialize its result without having to resort to
intermediate assertions. For example, suppose we wanted to prove
the following result: *)
Lemma plus_comm3 :
forall n m p, n + (m + p) = (p + m) + n.
(** It appears at first sight that we ought to be able to prove this
by rewriting with [plus_comm] twice to make the two sides match.
The problem, however, is that the second [rewrite] will undo the
effect of the first. *)
Proof.
intros n m p.
rewrite plus_comm.
rewrite plus_comm.
(* We are back where we started... *)
Abort.
(** One simple way of fixing this problem, using only tools that we
already know, is to use [assert] to derive a specialized version
of [plus_comm] that can be used to rewrite exactly where we
want. *)
Lemma plus_comm3_take2 :
forall n m p, n + (m + p) = (p + m) + n.
Proof.
intros n m p.
rewrite plus_comm.
assert (H : m + p = p + m).
{ rewrite plus_comm. reflexivity. }
rewrite H.
reflexivity.
Qed.
(** A more elegant alternative is to apply [plus_comm] directly to the
arguments we want to instantiate it with, in much the same way as
we apply a polymorphic function to a type argument. *)
Lemma plus_comm3_take3 :
forall n m p, n + (m + p) = (p + m) + n.
Proof.
intros n m p.
rewrite plus_comm.
rewrite (plus_comm m).
reflexivity.
Qed.
(** You can "use theorems as functions" in this way with almost all
tactics that take a theorem name as an argument. Note also that
theorem application uses the same inference mechanisms as function
application; thus, it is possible, for example, to supply
wildcards as arguments to be inferred, or to declare some
hypotheses to a theorem as implicit by default. These features
are illustrated in the proof below. *)
Example lemma_application_ex :
forall {n : nat} {ns : list nat},
In n (map (fun m => m * 0) ns) ->
n = 0.
Proof.
intros n ns H.
destruct (proj1 _ _ (In_map_iff _ _ _ _ _) H)
as [m [Hm _]].
rewrite mult_0_r in Hm. rewrite <- Hm. reflexivity.
Qed.
(** We will see many more examples of the idioms from this section in
later chapters. *)
(* ################################################################# *)
(** * Coq vs. Set Theory *)
(** Coq's logical core, the _Calculus of Inductive Constructions_,
differs in some important ways from other formal systems that are
used by mathematicians for writing down precise and rigorous
proofs. For example, in the most popular foundation for
mainstream paper-and-pencil mathematics, Zermelo-Fraenkel Set
Theory (ZFC), a mathematical object can potentially be a member of
many different sets; a term in Coq's logic, on the other hand, is
a member of at most one type. This difference often leads to
slightly different ways of capturing informal mathematical
concepts, but these are, by and large, quite natural and easy to
work with. For example, instead of saying that a natural number
[n] belongs to the set of even numbers, we would say in Coq that
[ev n] holds, where [ev : nat -> Prop] is a property describing
even numbers.
However, there are some cases where translating standard
mathematical reasoning into Coq can be either cumbersome or
sometimes even impossible, unless we enrich the core logic with
additional axioms. We conclude this chapter with a brief
discussion of some of the most significant differences between the
two worlds. *)
(* ================================================================= *)
(** ** Functional Extensionality *)
(** The equality assertions that we have seen so far mostly have
concerned elements of inductive types ([nat], [bool], etc.). But
since Coq's equality operator is polymorphic, these are not the
only possibilities -- in particular, we can write propositions
claiming that two _functions_ are equal to each other: *)
Example function_equality_ex1 : plus 3 = plus (pred 4).
Proof. reflexivity. Qed.
(** In common mathematical practice, two functions [f] and [g] are
considered equal if they produce the same outputs:
(forall x, f x = g x) -> f = g
This is known as the principle of _functional extensionality_.
Informally speaking, an "extensional property" is one that
pertains to an object's observable behavior. Thus, functional
extensionality simply means that a function's identity is
completely determined by what we can observe from it -- i.e., in
Coq terms, the results we obtain after applying it.
Functional extensionality is not part of Coq's basic axioms. This
means that some "reasonable" propositions are not provable. *)
Example function_equality_ex2 :
(fun x => plus x 1) = (fun x => plus 1 x).
Proof.
(* Stuck *)
Abort.
(** However, we can add functional extensionality to Coq's core logic
using the [Axiom] command. *)
Axiom functional_extensionality : forall {X Y: Type}
{f g : X -> Y},
(forall (x:X), f x = g x) -> f = g.
(** Using [Axiom] has the same effect as stating a theorem and
skipping its proof using [Admitted], but it alerts the reader that
this isn't just something we're going to come back and fill in
later!
We can now invoke functional extensionality in proofs: *)
Example function_equality_ex2 :
(fun x => plus x 1) = (fun x => plus 1 x).
Proof.
apply functional_extensionality. intros x.
apply plus_comm.
Qed.
(** Naturally, we must be careful when adding new axioms into Coq's
logic, as they may render it _inconsistent_ -- that is, they may
make it possible to prove every proposition, including [False]!
Unfortunately, there is no simple way of telling whether an axiom
is safe to add: hard work is generally required to establish the
consistency of any particular combination of axioms.
However, it is known that adding functional extensionality, in
particular, _is_ consistent.
To check whether a particular proof relies on any additional
axioms, use the [Print Assumptions] command. *)
Print Assumptions function_equality_ex2.
(* ===>
Axioms:
functional_extensionality :
forall (X Y : Type) (f g : X -> Y),
(forall x : X, f x = g x) -> f = g *)
(** **** Exercise: 4 stars (tr_rev) *)
(** One problem with the definition of the list-reversing function
[rev] that we have is that it performs a call to [app] on each
step; running [app] takes time asymptotically linear in the size
of the list, which means that [rev] has quadratic running time.
We can improve this with the following definition: *)
Fixpoint rev_append {X} (l1 l2 : list X) : list X :=
match l1 with
| [] => l2
| x :: l1' => rev_append l1' (x :: l2)
end.
Definition tr_rev {X} (l : list X) : list X :=
rev_append l [].
(** This version is said to be _tail-recursive_, because the recursive
call to the function is the last operation that needs to be
performed (i.e., we don't have to execute [++] after the recursive
call); a decent compiler will generate very efficient code in this
case. Prove that the two definitions are indeed equivalent. *)
Lemma tr_rev_correct : forall X, @tr_rev X = @rev X.
(* FILL IN HERE *) Admitted.
(** [] *)
(* ================================================================= *)
(** ** Propositions and Booleans *)
(** We've seen two different ways of encoding logical facts in Coq:
with _booleans_ (of type [bool]), and with _propositions_ (of type
[Prop]).
For instance, to claim that a number [n] is even, we can say
either
- (1) that [evenb n] returns [true], or
- (2) that there exists some [k] such that [n = double k].
Indeed, these two notions of evenness are equivalent, as
can easily be shown with a couple of auxiliary lemmas.
We often say that the boolean [evenb n] _reflects_ the proposition
[exists k, n = double k]. *)
Theorem evenb_double : forall k, evenb (double k) = true.
Proof.
intros k. induction k as [|k' IHk'].
- reflexivity.
- simpl. apply IHk'.
Qed.
(** **** Exercise: 3 stars (evenb_double_conv) *)
Theorem evenb_double_conv : forall n,
exists k, n = if evenb n then double k
else S (double k).
Proof.
(* Hint: Use the [evenb_S] lemma from [Induction.v]. *)
(* FILL IN HERE *) Admitted.
(** [] *)
Theorem even_bool_prop : forall n,
evenb n = true <-> exists k, n = double k.
Proof.
intros n. split.
- intros H. destruct (evenb_double_conv n) as [k Hk].
rewrite Hk. rewrite H. exists k. reflexivity.
- intros [k Hk]. rewrite Hk. apply evenb_double.
Qed.
(** Similarly, to state that two numbers [n] and [m] are equal, we can
say either (1) that [beq_nat n m] returns [true] or (2) that [n =
m]. These two notions are equivalent. *)
Theorem beq_nat_true_iff : forall n1 n2 : nat,
beq_nat n1 n2 = true <-> n1 = n2.
Proof.
intros n1 n2. split.
- apply beq_nat_true.
- intros H. rewrite H. rewrite <- beq_nat_refl. reflexivity.
Qed.
(** However, while the boolean and propositional formulations of a
claim are equivalent from a purely logical perspective, they need
not be equivalent _operationally_. Equality provides an extreme
example: knowing that [beq_nat n m = true] is generally of little
direct help in the middle of a proof involving [n] and [m];
however, if we convert the statement to the equivalent form [n =
m], we can rewrite with it.
The case of even numbers is also interesting. Recall that,
when proving the backwards direction of [even_bool_prop] (i.e.,
[evenb_double], going from the propositional to the boolean
claim), we used a simple induction on [k]. On the other hand, the
converse (the [evenb_double_conv] exercise) required a clever
generalization, since we can't directly prove [(exists k, n =
double k) -> evenb n = true].
For these examples, the propositional claims are more useful than
their boolean counterparts, but this is not always the case. For
instance, we cannot test whether a general proposition is true or
not in a function definition; as a consequence, the following code
fragment is rejected: *)
Fail Definition is_even_prime n :=
if n = 2 then true
else false.
(** Coq complains that [n = 2] has type [Prop], while it expects an
elements of [bool] (or some other inductive type with two
elements). The reason for this error message has to do with the
_computational_ nature of Coq's core language, which is designed
so that every function that it can express is computable and
total. One reason for this is to allow the extraction of
executable programs from Coq developments. As a consequence,
[Prop] in Coq does _not_ have a universal case analysis operation
telling whether any given proposition is true or false, since such
an operation would allow us to write non-computable functions.
Although general non-computable properties cannot be phrased as
boolean computations, it is worth noting that even many
_computable_ properties are easier to express using [Prop] than
[bool], since recursive function definitions are subject to
significant restrictions in Coq. For instance, the next chapter
shows how to define the property that a regular expression matches
a given string using [Prop]. Doing the same with [bool] would
amount to writing a regular expression matcher, which would be
more complicated, harder to understand, and harder to reason
about.
Conversely, an important side benefit of stating facts using
booleans is enabling some proof automation through computation
with Coq terms, a technique known as _proof by
reflection_. Consider the following statement: *)
Example even_1000 : exists k, 1000 = double k.
(** The most direct proof of this fact is to give the value of [k]
explicitly. *)
Proof. exists 500. reflexivity. Qed.
(** On the other hand, the proof of the corresponding boolean
statement is even simpler: *)
Example even_1000' : evenb 1000 = true.
Proof. reflexivity. Qed.
(** What is interesting is that, since the two notions are equivalent,
we can use the boolean formulation to prove the other one without
mentioning the value 500 explicitly: *)
Example even_1000'' : exists k, 1000 = double k.
Proof. apply even_bool_prop. reflexivity. Qed.
(** Although we haven't gained much in terms of proof size in this
case, larger proofs can often be made considerably simpler by the
use of reflection. As an extreme example, the Coq proof of the
famous _4-color theorem_ uses reflection to reduce the analysis of
hundreds of different cases to a boolean computation. We won't
cover reflection in great detail, but it serves as a good example
showing the complementary strengths of booleans and general
propositions. *)
(** **** Exercise: 2 stars (logical_connectives) *)
(** The following lemmas relate the propositional connectives studied
in this chapter to the corresponding boolean operations. *)
Lemma andb_true_iff : forall b1 b2:bool,
b1 && b2 = true <-> b1 = true /\ b2 = true.
Proof.
(* FILL IN HERE *) Admitted.
Lemma orb_true_iff : forall b1 b2,
b1 || b2 = true <-> b1 = true \/ b2 = true.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 1 star (beq_nat_false_iff) *)
(** The following theorem is an alternate "negative" formulation of
[beq_nat_true_iff] that is more convenient in certain
situations (we'll see examples in later chapters). *)
Theorem beq_nat_false_iff : forall x y : nat,
beq_nat x y = false <-> x <> y.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 3 stars (beq_list) *)
(** Given a boolean operator [beq] for testing equality of elements of
some type [A], we can define a function [beq_list beq] for testing
equality of lists with elements in [A]. Complete the definition
of the [beq_list] function below. To make sure that your
definition is correct, prove the lemma [beq_list_true_iff]. *)
Fixpoint beq_list {A : Type} (beq : A -> A -> bool)
(l1 l2 : list A) : bool
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Lemma beq_list_true_iff :
forall A (beq : A -> A -> bool),
(forall a1 a2, beq a1 a2 = true <-> a1 = a2) ->
forall l1 l2, beq_list beq l1 l2 = true <-> l1 = l2.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 2 stars, recommended (All_forallb) *)
(** Recall the function [forallb], from the exercise
[forall_exists_challenge] in chapter [Tactics]: *)
Fixpoint forallb {X : Type} (test : X -> bool) (l : list X) : bool :=
match l with
| [] => true
| x :: l' => andb (test x) (forallb test l')
end.
(** Prove the theorem below, which relates [forallb] to the [All]
property of the above exercise. *)
Theorem forallb_true_iff : forall X test (l : list X),
forallb test l = true <-> All (fun x => test x = true) l.
Proof.
(* FILL IN HERE *) Admitted.
(** Are there any important properties of the function [forallb] which
are not captured by this specification? *)
(* FILL IN HERE *)
(** [] *)
(* ================================================================= *)
(** ** Classical vs. Constructive Logic *)
(** We have seen that it is not possible to test whether or not a
proposition [P] holds while defining a Coq function. You may be
surprised to learn that a similar restriction applies to _proofs_!
In other words, the following intuitive reasoning principle is not
derivable in Coq: *)
Definition excluded_middle := forall P : Prop,
P \/ ~ P.
(** To understand operationally why this is the case, recall
that, to prove a statement of the form [P \/ Q], we use the [left]
and [right] tactics, which effectively require knowing which side
of the disjunction holds. But the universally quantified [P] in
[excluded_middle] is an _arbitrary_ proposition, which we know
nothing about. We don't have enough information to choose which
of [left] or [right] to apply, just as Coq doesn't have enough
information to mechanically decide whether [P] holds or not inside
a function. *)
(** However, if we happen to know that [P] is reflected in some
boolean term [b], then knowing whether it holds or not is trivial:
we just have to check the value of [b]. *)
Theorem restricted_excluded_middle : forall P b,
(P <-> b = true) -> P \/ ~ P.
Proof.
intros P [] H.
- left. rewrite H. reflexivity.
- right. rewrite H. intros contra. inversion contra.
Qed.
(** In particular, the excluded middle is valid for equations [n = m],
between natural numbers [n] and [m]. *)
Theorem restricted_excluded_middle_eq : forall (n m : nat),
n = m \/ n <> m.
Proof.
intros n m.
apply (restricted_excluded_middle (n = m) (beq_nat n m)).
symmetry.
apply beq_nat_true_iff.
Qed.
(** It may seem strange that the general excluded middle is not
available by default in Coq; after all, any given claim must be
either true or false. Nonetheless, there is an advantage in not
assuming the excluded middle: statements in Coq can make stronger
claims than the analogous statements in standard mathematics.
Notably, if there is a Coq proof of [exists x, P x], it is
possible to explicitly exhibit a value of [x] for which we can
prove [P x] -- in other words, every proof of existence is
necessarily _constructive_. *)
(** Logics like Coq's, which do not assume the excluded middle, are
referred to as _constructive logics_.
More conventional logical systems such as ZFC, in which the
excluded middle does hold for arbitrary propositions, are referred
to as _classical_. *)
(** The following example illustrates why assuming the excluded middle
may lead to non-constructive proofs:
_Claim_: There exist irrational numbers [a] and [b] such that [a ^
b] is rational.
_Proof_: It is not difficult to show that [sqrt 2] is irrational.
If [sqrt 2 ^ sqrt 2] is rational, it suffices to take [a = b =
sqrt 2] and we are done. Otherwise, [sqrt 2 ^ sqrt 2] is
irrational. In this case, we can take [a = sqrt 2 ^ sqrt 2] and
[b = sqrt 2], since [a ^ b = sqrt 2 ^ (sqrt 2 * sqrt 2) = sqrt 2 ^
2 = 2]. []
Do you see what happened here? We used the excluded middle to
consider separately the cases where [sqrt 2 ^ sqrt 2] is rational
and where it is not, without knowing which one actually holds!
Because of that, we wind up knowing that such [a] and [b] exist
but we cannot determine what their actual values are (at least,
using this line of argument).
As useful as constructive logic is, it does have its limitations:
There are many statements that can easily be proven in classical
logic but that have much more complicated constructive proofs, and
there are some that are known to have no constructive proof at
all! Fortunately, like functional extensionality, the excluded
middle is known to be compatible with Coq's logic, allowing us to
add it safely as an axiom. However, we will not need to do so in
this book: the results that we cover can be developed entirely
within constructive logic at negligible extra cost.
It takes some practice to understand which proof techniques must
be avoided in constructive reasoning, but arguments by
contradiction, in particular, are infamous for leading to
non-constructive proofs. Here's a typical example: suppose that
we want to show that there exists [x] with some property [P],
i.e., such that [P x]. We start by assuming that our conclusion
is false; that is, [~ exists x, P x]. From this premise, it is not
hard to derive [forall x, ~ P x]. If we manage to show that this
intermediate fact results in a contradiction, we arrive at an
existence proof without ever exhibiting a value of [x] for which
[P x] holds!
The technical flaw here, from a constructive standpoint, is that
we claimed to prove [exists x, P x] using a proof of
[~ ~ (exists x, P x)]. Allowing ourselves to remove double
negations from arbitrary statements is equivalent to assuming the
excluded middle, as shown in one of the exercises below. Thus,
this line of reasoning cannot be encoded in Coq without assuming
additional axioms. *)
(** **** Exercise: 3 stars (excluded_middle_irrefutable) *)
(** The consistency of Coq with the general excluded middle axiom
requires complicated reasoning that cannot be carried out within
Coq itself. However, the following theorem implies that it is
always safe to assume a decidability axiom (i.e., an instance of
excluded middle) for any _particular_ Prop [P]. Why? Because we
cannot prove the negation of such an axiom; if we could, we would
have both [~ (P \/ ~P)] and [~ ~ (P \/ ~P)], a contradiction. *)
Theorem excluded_middle_irrefutable: forall (P:Prop),
~ ~ (P \/ ~ P).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 3 stars, advanced (not_exists_dist) *)
(** It is a theorem of classical logic that the following two
assertions are equivalent:
~ (exists x, ~ P x)
forall x, P x
The [dist_not_exists] theorem above proves one side of this
equivalence. Interestingly, the other direction cannot be proved
in constructive logic. Your job is to show that it is implied by
the excluded middle. *)
Theorem not_exists_dist :
excluded_middle ->
forall (X:Type) (P : X -> Prop),
~ (exists x, ~ P x) -> (forall x, P x).
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(** **** Exercise: 5 stars, optional (classical_axioms) *)
(** For those who like a challenge, here is an exercise taken from the
Coq'Art book by Bertot and Casteran (p. 123). Each of the
following four statements, together with [excluded_middle], can be
considered as characterizing classical logic. We can't prove any
of them in Coq, but we can consistently add any one of them as an
axiom if we wish to work in classical logic.
Prove that all five propositions (these four plus
[excluded_middle]) are equivalent. *)
Definition peirce := forall P Q: Prop,
((P->Q)->P)->P.
Definition double_negation_elimination := forall P:Prop,
~~P -> P.
Definition de_morgan_not_and_not := forall P Q:Prop,
~(~P /\ ~Q) -> P\/Q.
Definition implies_to_or := forall P Q:Prop,
(P->Q) -> (~P\/Q).
(* FILL IN HERE *)
(** [] *)
(** $Date: 2017-04-26 17:33:43 -0400 (Wed, 26 Apr 2017) $ *)
|