8
8
9
9
> % default total
10
10
11
+
11
12
== Pairs of Numbers
12
13
13
14
In an inductive type definition, each constructor can take any number of
@@ -94,20 +95,23 @@ match in `fst` and `snd`. We can do this with `case`.
94
95
Notice that `case` matches just one pattern here. That's because `NatProd` s can
95
96
only be constructed in one way.
96
97
98
+
97
99
=== Exercise : 1 star (snd_fst_is_swap)
98
100
99
101
> snd_fst_is_swap : (p : NatProd) -> (snd p, fst p) = swap_pair p
100
102
> snd_fst_is_swap p = ? snd_fst_is_swap_rhs
101
103
102
104
$\ square$
103
105
106
+
104
107
=== Exercise : 1 star, optional (fst_swap_is_snd)
105
108
106
109
> fst_swap_is_snd : (p : NatProd) -> fst (swap_pair p) = snd p
107
110
> fst_swap_is_snd p = ? fst_swap_is_snd_rhs
108
111
109
112
$\ square$
110
113
114
+
111
115
== Lists of Numbers
112
116
113
117
Generalizing the definition of pairs, we can describe the type of _lists_ of
@@ -168,6 +172,7 @@ square-bracket notation for lists; the right-hand side of the third one
168
172
illustrates Coq's syntax for declaring n-ary notations and translating them to
169
173
nested sequences of binary constructors.
170
174
175
+
171
176
=== Repeat
172
177
173
178
A number of functions are useful for manipulating lists. For example, the
@@ -178,6 +183,7 @@ A number of functions are useful for manipulating lists. For example, the
178
183
> repeat n Z = Nil
179
184
> repeat n (S k) = n :: repeat n k
180
185
186
+
181
187
=== Length
182
188
183
189
The `length` function calculates the length of a list.
@@ -186,6 +192,7 @@ The `length` function calculates the length of a list.
186
192
> length Nil = Z
187
193
> length (h :: t) = S (length t)
188
194
195
+
189
196
=== Append
190
197
191
198
The `app` function concatenates (appends) two lists.
@@ -208,6 +215,7 @@ convenient to have an infix operator for it.
208
215
> test_app3 : ((1::2::3::[]) ++ []) = (1::2::3::[])
209
216
> test_app3 = Refl
210
217
218
+
211
219
=== Head (with default) and Tail
212
220
213
221
Here are two smaller examples of programming with lists. The `hd` function
@@ -232,6 +240,7 @@ first element, so we must pass a default value to be returned in that case.
232
240
> test_tl : tl (1::2::3::[]) = (2::3::[])
233
241
> test_tl = Refl
234
242
243
+
235
244
=== Exercises
236
245
237
246
==== Exercise: 2 stars, recommended (list_funs)
@@ -259,6 +268,7 @@ below. Have a look at the tests to understand what these functions should do.
259
268
260
269
$\square$
261
270
271
+
262
272
==== Exercise: 3 stars, advanced (alternate)
263
273
264
274
Complete the definition of `alternate`, which " zips up" two lists into one,
@@ -289,6 +299,7 @@ requires defining a new kind of pairs, but this is not the only way.)
289
299
290
300
$\square$
291
301
302
+
292
303
=== Bags via Lists
293
304
294
305
A `bag` (or `multiset`) is like a set, except that each element can appear
@@ -298,6 +309,7 @@ represent a bag of numbers as a list.
298
309
> Bag : Type
299
310
> Bag = NatList
300
311
312
+
301
313
==== Exercise: 3 stars, recommended (bag_functions)
302
314
303
315
Complete the following definitions for the functions `count`, `sum`, `add`, and
@@ -352,6 +364,7 @@ functions that have already been defined.
352
364
353
365
$\square$
354
366
367
+
355
368
==== Exercise: 3 stars, optional (bag_more_functions)
356
369
357
370
Here are some more bag functions for you to practice with.
@@ -386,7 +399,7 @@ return the same bag unchanged.
386
399
> test_remove_all3 : count 4 (remove_all 5 (2::1::5::4::1::4::[])) = 2
387
400
> test_remove_all3 = ?test_remove_all3_rhs
388
401
389
- > test_remove_all4 : count 5
402
+ > test_remove_all4 : count 5
390
403
> (remove_all 5 (2::1::5::4::5::1::4::5::1::4::[])) = 0
391
404
> test_remove_all4 = ?test_remove_all4_rhs
392
405
@@ -401,6 +414,7 @@ return the same bag unchanged.
401
414
402
415
$\square$
403
416
417
+
404
418
==== Exercise: 3 stars, recommended (bag_theorem)
405
419
406
420
Write down an interesting theorem `bag_theorem` about bags involving the
@@ -413,6 +427,7 @@ ask for help if you get stuck!
413
427
414
428
$\square$
415
429
430
+
416
431
== Reasoning About Lists
417
432
418
433
As with numbers, simple facts about list-processing functions can sometimes be
@@ -441,13 +456,15 @@ tail of the list it is constructing).
441
456
Usually, though, interesting theorems about lists require induction for their
442
457
proofs.
443
458
459
+
444
460
==== Micro-Sermon
445
461
446
462
Simply reading example proof scripts will not get you very far! It is important
447
463
to work through the details of each one, using Idris and thinking about what
448
464
each step achieves. Otherwise it is more or less guaranteed that the exercises
449
465
will make no sense when you get to them. 'Nuff said.
450
466
467
+
451
468
=== Induction on Lists
452
469
453
470
Proofs by induction over datatypes like `NatList` are a little less familiar
@@ -512,6 +529,7 @@ _Proof_: By induction on `l1`.
512
529
`n :: ((l1' ++ l2) ++ l 3) = n :: (l1' ++ (l2 ++ l3))`,
513
530
which is immediate from the induction hypothesis. $\square$
514
531
532
+
515
533
==== Reversing a List
516
534
517
535
For a slightly more involved example of inductive proof over lists, suppose we
@@ -527,6 +545,7 @@ use `app` to define a list-reversing function `rev`:
527
545
> test_rev2 : rev Nil = Nil
528
546
> test_rev2 = Refl
529
547
548
+
530
549
==== Properties of rev
531
550
532
551
Now let's prove some theorems about our newly defined `rev`. For something a bit
@@ -583,7 +602,7 @@ _Proof_: By induction on `l1`.
583
602
584
603
- First, suppose `l1 = []`. We must show
585
604
`length ([] ++ l2) = length [] + length l2`,
586
- which follows directly from the definitions of `length` and `++`.
605
+ which follows directly from the definitions of `length` and `++`.
587
606
588
607
- Next, suppose `l1 = n :: l1'`, with
589
608
`length (l1' ++ l2) = length l1' + length l2`.
@@ -650,6 +669,7 @@ the book; it can save you a lot of time!
650
669
If you are using ProofGeneral, you can run Search with C-c C-a C-a. Pasting its
651
670
response into your buffer can be accomplished with C-c C-;.
652
671
672
+
653
673
=== List Exercises, Part 1
654
674
655
675
==== Exercise: 3 stars (list_exercises)
@@ -680,6 +700,7 @@ An exercise about your implementation of `nonzeros`:
680
700
681
701
$\square$
682
702
703
+
683
704
==== Exercise: 2 stars (beq_NatList)
684
705
685
706
Fill in the definition of `beq_NatList`, which compares lists of numbers for
@@ -702,6 +723,7 @@ equality. Prove that `beq_NatList l l` yields `True` for every list `l`.
702
723
703
724
$\square$
704
725
726
+
705
727
=== List Exercises, Part 2
706
728
707
729
==== Exercise: 3 stars, advanced (bag_proofs)
@@ -726,6 +748,7 @@ The following lemma about `leb` might help you in the next proof.
726
748
727
749
$\square$
728
750
751
+
729
752
==== Exercise: 3 stars, optional (bag_count_sum)
730
753
731
754
Write down an interesting theorem `bag_count_sum` about bags involving the
@@ -736,6 +759,7 @@ the proof depends on how you defined `count`!)
736
759
737
760
$\square$
738
761
762
+
739
763
==== Exercise: 4 stars, advanced (rev_injective)
740
764
741
765
Prove that the `rev` function is injective -- that is,
@@ -747,6 +771,7 @@ Prove that the `rev` function is injective -- that is,
747
771
748
772
$\square$
749
773
774
+
750
775
== Options
751
776
752
777
Suppose we want to write a function that returns the `n`th element of some list.
@@ -811,6 +836,7 @@ default in the `None` case.
811
836
> option_elim d (Some k) = k
812
837
> option_elim d None = d
813
838
839
+
814
840
==== Exercise: 2 stars (hd_error)
815
841
816
842
Using the same idea, fix the `hd` function from earlier so we don't have to pass
@@ -830,6 +856,7 @@ a default element for the `Nil` case.
830
856
831
857
$\square$
832
858
859
+
833
860
==== Exercise: 1 star, optional (option_elim_hd)
834
861
835
862
This exercise relates your new `hd_error` to the old `hd`.
@@ -840,6 +867,7 @@ This exercise relates your new `hd_error` to the old `hd`.
840
867
841
868
$\square$
842
869
870
+
843
871
== Partial Maps
844
872
845
873
As a final illustration of how data structures can be defined in Idris, here is
@@ -861,6 +889,7 @@ We'll also need an equality test for `Id`s:
861
889
> beq_id : (x1, x2 : Id) -> Bool
862
890
> beq_id (MkId n1) (MkId n2) = beq_nat n1 n2
863
891
892
+
864
893
==== Exercise: 1 star (beq_id_refl)
865
894
866
895
> beq_id_refl : (x : Id) -> True = beq_id x x
@@ -898,6 +927,7 @@ first one it encounters.
898
927
> then Some v
899
928
> else find x d'
900
929
930
+
901
931
==== Exercise: 1 star (update_eq)
902
932
903
933
> update_eq : (d : PartialMap) -> (x : Id) -> (v : Nat) ->
@@ -906,6 +936,7 @@ first one it encounters.
906
936
907
937
$\square$
908
938
939
+
909
940
==== Exercise: 1 star (update_neq)
910
941
911
942
> update_neq : (d : PartialMap) -> (x, y : Id ) -> (o : Nat) ->
@@ -915,6 +946,7 @@ $\square$
915
946
916
947
$\square$
917
948
949
+
918
950
==== Exercise: 2 stars (baz_num_elts)
919
951
920
952
Consider the following inductive definition:
@@ -926,4 +958,4 @@ Consider the following inductive definition:
926
958
How _many_ elements does the type `Baz` have? (Answer in English or the natural
927
959
language of your choice.)
928
960
929
- $\square$
961
+ $\square$
0 commit comments