Lists

Table of Contents


Homepage | Previous: Induction | Code | Next: Polymorphism

1. Summary

This chapter introduces foundational proof techniques in Coq using lists, pairs, and basic functional programming constructs.

1.1. Terms

Search, pairs, lists, partial maps, options, bags.

2. Notes

2.1. Pairs of Numbers

  • Defined an inductive type natprod for pairs of numbers.
  • Introduced proofs using destruct and simplification.
    • Example: Proved surjective pairing by destructing pairs into components.

2.2. Lists of Numbers

  • Introduced the inductive type natlist for lists of natural numbers.
  • Examples of recursive functions:
    • length: Calculate the length of a list.
    • app: Append two lists.
    • nonzeros: Filter out zeros from a list.

Proof Techniques:

  • Induction:
    • Used induction over lists for proofs.
    • Example: Proved app_assoc (associativity of list append) using list induction.
  • Case Analysis:
    • Example: Proved tl_length_pred by analyzing whether the list is empty or non-empty.

2.3. Generalizing Statements

  • Demonstrated generalizing theorems for stronger inductive hypotheses.
    • Example: Proved repeat_plus for generalized sums of repeated lists.

2.4. Reversing a List

  • Defined rev, a function to reverse lists.
  • Proved properties of rev:
    • rev_length: Reversing a list does not change its length.
    • rev_involutive: Reversing a list twice gives the original list.
  • Key Proof Techniques:
    • Leveraging helper lemmas such as app_length.
    • Structuring proofs with auxiliary results when stuck.

2.5. Bags (Multisets)

  • Introduced bags as lists with additional functions:
    • count: Count occurrences of an element.
    • sum: Combine two bags.
    • add: Add an element to a bag.
    • member: Check if an element exists in a bag.
  • Proof Techniques:
    • Direct reasoning with destruct.
    • Example: Proved add_inc_count (adding increases count) by case analysis.

2.6. Reasoning About Lists

  • Explored techniques for proving list properties:
    • Example: rev_app_distr: Proved that reversing an appended list distributes over the append.
    • Used helper theorems (app_assoc, app_length) for modular reasoning.

2.7. Options

  • Introduced natoption to handle partial functions safely.
  • Defined functions like nth_error and hd_error for lists with proper error handling.
  • Proved equivalence between implementations:
    • Example: Related hd_error to an earlier implementation using a default value.

2.8. Partial Maps

  • Defined partial maps using an inductive type partial_map.
  • Key functions:
    • update: Add or override key-value pairs.
    • find: Retrieve a value for a key.
  • Proof Techniques:
    • Case analysis and rewrite.
    • Example: Proved update_eq (finding an updated key retrieves the value) using eqb_id_refl.

2.9. Techniques Summary

  1. Simplification:
    • Simplify goals using simpl and reflexivity.
  2. Case Analysis:
    • Analyze inductive data types using destruct.
  3. Induction:
    • Apply structural induction for proofs involving recursive data structures.
  4. Helper Lemmas:
    • Prove auxiliary results to support complex proofs.
  5. Search:
    • Use Search to find existing results for reuse in proofs.

3. Exercises

This section lists all the exercises from the Coq file, their respective points, and how they were solved.

3.1. snd_fst_is_swap

  • Solution: Used destruct to decompose the pair and applied reflexivity.

3.2. fst_swap_is_snd

  • Solution: Used destruct to decompose the pair and applied reflexivity.

3.3. list_funs

  • nonzeros: Defined using match with an if statement to filter out zeros.
  • oddmembers: Used a helper function odd to filter odd numbers recursively.
  • countoddmembers: Used length on the result of oddmembers to count odd elements.

3.4. alternate

  • Solution: Used simultaneous pattern matching on two lists (l1, l2) to interleave elements recursively.

3.5. bag_functions

  • Solution:
    • count: Used recursion and if to count occurrences.
    • sum: Defined as app (list append).
    • add: Pre-pended the element to the bag.
    • member: Checked membership using recursion and if.

3.6. remove_one

  • Solution: Recursively removed the first occurrence of the given element using an if condition.

3.7. remove_all

  • Solution: Removed all occurrences of the given element using recursion and if.

3.8. included

  • Solution: Used count and remove_one recursively to check if all elements of one bag are in another.

3.9. add_inc_count

  • Solution: Proved using simplification and a helper lemma for equality (n =? n = true).

3.10. eqblist

  • eqblist: Defined a recursive equality check for two lists.
  • eqblist_refl: Proved by induction and simplification using eq_eq.

3.11. count_member_nonzero

  • Solution: Simplified the expression to prove that adding 1 ensures its count is non-zero.

3.12. count_member_n_nonzero

  • Solution: Generalized count_member_nonzero for any number using simplification and destruct.

3.13. remove_does_not_increase_count

  • Solution: Used induction over the bag and helper lemmas for comparison (leb).

3.14. bag_count_sum

  • Solution: Proved that the count of an element in the sum of two bags equals the sum of individual counts.

3.15. involution_injective

  • Solution: Proved that every involution is injective by assuming f(f(x)) = x and using symmetry in reasoning.

3.16. rev_injective

  • Solution: Proved injectivity of rev by reasoning about rev(rev(x)) = x.

3.17. hd_error

  • Solution: Returned None for an empty list and Some for the head of a non-empty list using match.

3.18. option_elim_hd

  • Solution: Related hd_error to the earlier hd using destruct and simplification.

3.19. eqb_id_refl

  • Solution: Proved reflexivity of eqb_id using destruct and eqb_refl.

3.20. =updateeq

  • Solution: Proved using simplification and the reflexivity of eqb_id.

3.21. updateneq

  • Solution: Used simplification and the hypothesis eqb_id x y = false.

4. Scores

Name Points Notes Completed?
snd_fst_is_swap 1 Standard Yes
fst_swap_is_snd 1 Optional Yes
list_funs 2 Standard Yes
alternate 3 Advanced Yes
bag_functions 3 Standard Yes
remove_one 3 Optional Yes
remove_all 3 Optional Yes
included 3 Optional Yes
add_inc_count 2 Especially useful Yes
eqblist 2 Standard Yes
count_member_nonzero 1 Standard Yes
count_member_n_nonzero 1 Standard Yes
remove_does_not_increase_count 3 Advanced Yes
bag_count_sum 3 Standard Yes
involution_injective 3 Advanced Yes
rev_injective 2 Advanced Yes
hd_error 2 Standard Yes
option_elim_hd 1 Optional Yes
eqb_id_refl 1 Standard Yes
update_eq 1 Standard Yes
update_neq 1 Standard Yes

Total Points: 47/47

5. Questions

5.1. TODO Non-decreasing inductive data types

What if we have infinite lists - how will Coq know whether functions over such data types terminates?

Inductive nat_stream : Type :=
  | Cons (n : nat) (s : nat_stream).

Fixpoint until_n (n : nat) (s : nat_stream) : natlist :=
  match n with
  | 0 => []
  | S n' => match s with
            | Cons x s' => x :: until n' s'
            end
  end.

Fixpoint unravel (s : nat_stream) : natlist :=
   match s with
   | Cons x s' => x :: unravel s'
   end.

Here, apparently, both until and unravel terminate (or Coq doesn’t complain). Why? I thought unravel would run infinitely since natstream is “infinite”? q

6. Metacognition

This was a straightforward chapter. The concepts were familiar and I don’t have any particular questions directly related to the material. The exercises were straightforward too. There really wasn’t any thing notable (that isn’t already familiar to me with SML). Hence, this time, I used ChatGPT to take notes. The most important takeaway is that destruct works on terms, and that generalizing identities might be easier to prove / make other results easier to prove.

7. Further Knowledge

N/A

8. TODOs

8.1. Scores

Author: selffins

Created: 2025-04-12 Sat 22:31