4
4
5
5
> import Basics
6
6
7
- > % hide Basics . Numbers . pred
7
+ > % access public export
8
+
9
+ > % hide Basics . Numbers . pred
8
10
> % hide Basics . Playground2 . plus
9
11
10
12
In previous chapters, we have seen many examples of factual claims
11
13
(_propositions_) and ways of presenting evidence of their truth (_proofs_). In
12
14
particular, we have worked extensively with equality propositions of the form
13
15
\ idr{e1 = e2}, with implications (\ idr{p -> q}), and with quantified
14
16
propositions (\ idr{x -> P (x)}). In this chapter, we will see how Idris can be
15
- used to carry out other familiar forms of logical reasoning.
17
+ used to carry out other familiar forms of logical reasoning.
16
18
17
19
Before diving into details, let 's talk a bit about the status of mathematical
18
20
statements in Idris . Recall that Idris is a _typed_ language, which means that
@@ -57,7 +59,7 @@ type signatures.
57
59
But propositions can be used in many other ways. For example, we can give a name
58
60
to a proposition as a value on its own, just as we have given names to
59
61
expressions of other sorts (you'll soon see why we start the name with a capital
60
- letter).
62
+ letter).
61
63
62
64
> Plus_fact : Type
63
65
> Plus_fact = 2 + 2 = 4
@@ -82,7 +84,7 @@ arguments of some type and return a proposition. For instance, the following
82
84
function takes a number and returns a proposition asserting that this number is
83
85
equal to three :
84
86
85
- > is_three : Nat -> Type
87
+ > is_three : Nat -> Type
86
88
> is_three n = n= 3
87
89
88
90
`` `idris
@@ -171,8 +173,8 @@ intermediate steps in proofs, especially in bigger developments. Here's a simple
171
173
example :
172
174
173
175
> and_example3 : (n, m : Nat ) -> n + m = 0 -> n * m = 0
174
- > and_example3 n m prf =
175
- > let (nz, _ ) = and_exercise n m prf in
176
+ > and_example3 n m prf =
177
+ > let (nz, _ ) = and_exercise n m prf in
176
178
> rewrite nz in Refl
177
179
178
180
\ todo[inline]{Remove lemma and exercise, use \ idr{fst } and \ idr{snd } directly? }
@@ -344,7 +346,7 @@ Write an informal proof of \idr{double_neg}:
344
346
345
347
_Theorem_ : \idr{p} implies \idr{Not $ Not p}, for any proposition \idr{p}.
346
348
347
- > -- FILL IN HERE
349
+ > -- FILL IN HERE
348
350
349
351
$\ square$
350
352
@@ -369,7 +371,7 @@ $\square$
369
371
370
372
Write an informal proof (in English ) of the proposition \ idr{Not (p, Not p)}.
371
373
372
- > -- FILL IN HERE
374
+ > -- FILL IN HERE
373
375
374
376
$\ square$
375
377
@@ -484,16 +486,16 @@ We can now use these facts with \idr{rewrite} and \idr{Refl} to give smooth
484
486
proofs of statements involving equivalences. Here is a ternary version of the
485
487
previous \ idr{mult_0} result :
486
488
487
- > mult_0_3 : (n * m * p = Z) <->
489
+ > mult_0_3 : (n * m * p = Z) <->
488
490
> ((n = Z) `Either ` ((m = Z) `Either ` (p = Z)))
489
491
> mult_0_3 = (to, fro)
490
- > where
492
+ > where
491
493
> to : (n * m * p = Z) -> ((n = Z) `Either ` ((m = Z) `Either ` (p = Z)))
492
- > to {n} {m} {p} prf = let
494
+ > to {n} {m} {p} prf = let
493
495
> (nm_p_to, _ ) = mult_0 {n= (n* m)} {m= p}
494
496
> (n_m_to, _ ) = mult_0 {n} {m}
495
497
> (_ , or_a_fro) = or_assoc {p= (n= Z )} {q= (m= Z )} {r= (p= Z )}
496
- > in or_a_fro $ case nm_p_to prf of
498
+ > in or_a_fro $ case nm_p_to prf of
497
499
> Left prf => Left $ n_m_to prf
498
500
> Right prf => Right prf
499
501
> fro : ((n = Z) `Either ` ((m = Z) `Either ` (p = Z))) -> (n * m * p = Z)
@@ -504,7 +506,7 @@ previous \idr{mult_0} result:
504
506
The apply tactic can also be used with \ idr{<-> }. When given an equivalence as
505
507
its argument, apply tries to guess which side of the equivalence to use.
506
508
507
- > apply_iff_example : (n, m : Nat ) -> n * m = Z -> ((n = Z) `Either ` (m = Z))
509
+ > apply_iff_example : (n, m : Nat ) -> n * m = Z -> ((n = Z) `Either ` (m = Z))
508
510
> apply_iff_example n m = fst $ mult_0 {n} {m}
509
511
510
512
@@ -549,7 +551,7 @@ $\square$
549
551
550
552
Prove that existential quantification distributes over disjunction.
551
553
552
- > dist_exists_or : {p, q : a -> Type } -> (x ** (p x `Either ` q x)) <->
554
+ > dist_exists_or : {p, q : a -> Type } -> (x ** (p x `Either ` q x)) <->
553
555
> ((x ** p x) `Either ` (x ** q x))
554
556
> dist_exists_or = ? dist_exists_or_rhs
555
557
@@ -593,7 +595,7 @@ We can also prove more generic, higher-level lemmas about \idr{In}.
593
595
Note , in the next, how \ idr{In } starts out applied to a variable and only gets
594
596
expanded when we do case analysis on this variable :
595
597
596
- > In_map : (f : a -> b) -> (l : List a) -> (x : a) -> In x l ->
598
+ > In_map : (f : a -> b) -> (l : List a) -> (x : a) -> In x l ->
597
599
> In (f x) (map f l)
598
600
> In_map _ [] _ ixl = absurd ixl
599
601
> In_map f (x' :: xs) x (Left prf) = rewrite prf in Left Refl
@@ -609,7 +611,7 @@ set of strengths and limitations.
609
611
610
612
==== Exercise : 2 stars (In_map_iff)
611
613
612
- > In_map_iff : (f : a -> b) -> (l : List a) -> (y : b) ->
614
+ > In_map_iff : (f : a -> b) -> (l : List a) -> (y : b) ->
613
615
> (In y (map f l)) <-> (x ** (f x = y, In x l))
614
616
> In_map_iff f l y = ? In_map_iff_rhs
615
617
@@ -758,7 +760,7 @@ A more elegant alternative is to apply \idr{plusCommutative} directly to the
758
760
arguments we want to instantiate it with , in much the same way as we apply a
759
761
polymorphic function to a type argument.
760
762
761
- > plus_comm3 n m p = rewrite plusCommutative n (m+ p) in
763
+ > plus_comm3 n m p = rewrite plusCommutative n (m+ p) in
762
764
> rewrite plusCommutative m p in Refl
763
765
764
766
You can " use theorems as functions" in this way with almost all tactics that
@@ -768,12 +770,12 @@ example, to supply wildcards as arguments to be inferred, or to declare some
768
770
hypotheses to a theorem as implicit by default. These features are illustrated
769
771
in the proof below.
770
772
771
- > lemma_application_ex : (n : Nat ) -> (ns : List Nat ) ->
773
+ > lemma_application_ex : (n : Nat ) -> (ns : List Nat ) ->
772
774
> In n (map (\m => m * 0) ns) -> n = 0
773
775
> lemma_application_ex _ [] prf = absurd prf
774
- > lemma_application_ex _ (y :: _ ) (Left prf) =
776
+ > lemma_application_ex _ (y :: _ ) (Left prf) =
775
777
> rewrite sym $ multZeroRightZero y in sym prf
776
- > lemma_application_ex n (_ :: xs) (Right prf) =
778
+ > lemma_application_ex n (_ :: xs) (Right prf) =
777
779
> lemma_application_ex n xs prf
778
780
779
781
We will see many more examples of the idioms from this section in later chapters.
@@ -850,7 +852,7 @@ that this isn't just something we're going to come back and fill in later!
850
852
We can now invoke functional extensionality in proofs :
851
853
852
854
> function_equality_ex2 : (\x => plus x 1) = (\x => plus 1 x)
853
- > function_equality_ex2 = functional_extensionality $ \ x => plusCommutative x 1
855
+ > function_equality_ex2 = functional_extensionality $ \ x => plusCommutative x 1
854
856
855
857
Naturally , we must be careful when adding new axioms into Idris's logic, as they
856
858
may render it _inconsistent_ -- that is, they may make it possible to prove
@@ -883,7 +885,7 @@ Print Assumptions function_equality_ex2.
883
885
One problem with the definition of the list- reversing function \ idr{rev} that we
884
886
have is that it performs a call to \ idr{++ } on each step; running \ idr{++ } takes
885
887
time asymptotically linear in the size of the list, which means that \ idr{rev}
886
- has quadratic running time.
888
+ has quadratic running time.
887
889
888
890
> rev : (l : List x) -> List x
889
891
> rev [] = []
@@ -928,8 +930,8 @@ For instance, to claim that a number \idr{n} is even, we can say either
928
930
We often say that the boolean \ idr{evenb n} _reflects_ the proposition \ idr{(k
929
931
** n = double k)}.
930
932
931
- > double : (n : Nat ) -> Nat
932
- > double Z = Z
933
+ > double : (n : Nat ) -> Nat
934
+ > double Z = Z
933
935
> double (S k) = S (S (double k))
934
936
935
937
> evenb_double : evenb (double k) = True
@@ -952,8 +954,8 @@ $\square$
952
954
> where
953
955
> to : evenb n = True -> (k ** n = double k)
954
956
> to {n} prf = let
955
- > (k ** p) = evenb_double_conv {n}
956
- > in
957
+ > (k ** p) = evenb_double_conv {n}
958
+ > in
957
959
958
960
\ todo[inline]{Is there a shorter way? }
959
961
@@ -973,10 +975,10 @@ These two notions are equivalent.
973
975
> beq_nat_true {n= Z } {m= (S _ )} Refl impossible
974
976
> beq_nat_true {n= (S n')} {m= (S m')} eq =
975
977
> rewrite beq_nat_true {n= n'} {m= m'} eq in Refl
976
-
978
+
977
979
> beq_nat_refl : (n : Nat ) -> True = beq_nat n n
978
980
> beq_nat_refl Z = Refl
979
- > beq_nat_refl (S k) = beq_nat_refl k
981
+ > beq_nat_refl (S k) = beq_nat_refl k
980
982
981
983
> beq_nat_true_iff : (n1, n2 : Nat ) -> (beq_nat n1 n2 = True) <-> (n1 = n2)
982
984
> beq_nat_true_iff n1 n2 = (to, fro n1 n2)
@@ -1068,11 +1070,11 @@ showing the complementary strengths of booleans and general propositions.
1068
1070
The following lemmas relate the propositional connectives studied in this
1069
1071
chapter to the corresponding boolean operations.
1070
1072
1071
- > andb_true_iff : (b1, b2 : Bool ) -> (b1 && b2 = True) <->
1073
+ > andb_true_iff : (b1, b2 : Bool ) -> (b1 && b2 = True) <->
1072
1074
> (b1 = True, b2 = True)
1073
1075
> andb_true_iff b1 b2 = ? andb_true_iff_rhs
1074
1076
1075
- > orb_true_iff : (b1, b2 : Bool ) -> (b1 || b2 = True) <->
1077
+ > orb_true_iff : (b1, b2 : Bool ) -> (b1 || b2 = True) <->
1076
1078
> ((b1 = True) `Either ` (b2 = True))
1077
1079
> orb_true_iff b1 b2 = ? orb_true_iff_rhs
1078
1080
@@ -1102,7 +1104,7 @@ function below. To make sure that your definition is correct, prove the lemma
1102
1104
> beq_list : (beq : a -> a -> Bool ) -> (l1, l2 : List a) -> Bool
1103
1105
> beq_list beq l1 l2 = ? beq_list_rhs
1104
1106
1105
- > beq_list_true_iff : (beq : a -> a -> Bool ) ->
1107
+ > beq_list_true_iff : (beq : a -> a -> Bool ) ->
1106
1108
> ((a1, a2 : a) -> (beq a1 a2 = True) <-> (a1 = a2)) ->
1107
1109
> ((l1, l2 : List a) -> (beq_list beq l1 l2 = True) <-> (l1 = l2))
1108
1110
> beq_list_true_iff beq f l1 l2 = ? beq_list_true_iff_rhs
@@ -1118,18 +1120,18 @@ Recall the function \idr{forallb}, from the exercise
1118
1120
> forallb : (test : x -> Bool ) -> (l : List x) -> Bool
1119
1121
> forallb _ [] = True
1120
1122
> forallb test (x :: xs) = test x && forallb test xs
1121
-
1123
+
1122
1124
Prove the theorem below, which relates \ idr{forallb} to the \ idr{All } property
1123
1125
of the above exercise.
1124
1126
1125
- > forallb_true_iff : (l : List x) -> (forallb test l = True) <->
1127
+ > forallb_true_iff : (l : List x) -> (forallb test l = True) <->
1126
1128
> (All (\x => test x = True) l)
1127
1129
> forallb_true_iff l = ? forallb_true_iff_rhs
1128
1130
1129
1131
Are there any important properties of the function \ idr{forallb} which are not
1130
1132
captured by this specification?
1131
1133
1132
- > -- FILL IN HERE
1134
+ > -- FILL IN HERE
1133
1135
1134
1136
$\ square$
1135
1137
@@ -1158,12 +1160,6 @@ However, if we happen to know that \idr{p} is reflected in some boolean term
1158
1160
\ idr{b}, then knowing whether it holds or not is trivial : we just have to check
1159
1161
the value of \ idr{b}.
1160
1162
1161
- \ todo[inline]{Remove when a release with
1162
- https : //github.com/idris-lang/Idris-dev/pull/3925 happens}
1163
-
1164
- > Uninhabited (False = True ) where
1165
- > uninhabited Refl impossible
1166
-
1167
1163
> restricted_excluded_middle : (p <-> b = True) -> p `Either ` Not p
1168
1164
> restricted_excluded_middle {b = True } (_ , bp) = Left $ bp Refl
1169
1165
> restricted_excluded_middle {b = False } (pb, _ ) = Right $ uninhabited . pb
@@ -1174,9 +1170,9 @@ natural numbers \idr{n} and \idr{m}.
1174
1170
\ todo[inline]{Is there a simpler way to write this? Maybe with setoids? }
1175
1171
1176
1172
> restricted_excluded_middle_eq : (n, m : Nat ) -> (n = m) `Either ` Not (n = m)
1177
- > restricted_excluded_middle_eq n m =
1173
+ > restricted_excluded_middle_eq n m =
1178
1174
> restricted_excluded_middle (to n m, fro n m)
1179
- > where
1175
+ > where
1180
1176
> to : (n, m : Nat ) -> (n=m) -> (n==m)=True
1181
1177
> to Z Z prf = Refl
1182
1178
> to Z (S _ ) Refl impossible
0 commit comments