2 (** {1 Polymorphic Lists} *)
4 (** {2 Basic theory of polymorphic lists} *)
8 type list 'a = Nil | Cons 'a (list 'a)
10 let predicate is_nil (l:list 'a)
11 ensures { result <-> l = Nil }
13 match l with Nil -> true | Cons _ _ -> false end
17 (** {2 Length of a list} *)
24 let rec function length (l: list 'a) : int =
27 | Cons _ r -> 1 + length r
30 lemma Length_nonnegative: forall l: list 'a. length l >= 0
32 lemma Length_nil: forall l: list 'a. length l = 0 <-> l = Nil
36 (** {2 Membership in a list} *)
41 predicate mem (x: 'a) (l: list 'a) = match l with
43 | Cons y r -> x = y \/ mem x r
48 (** {2 Quantifiers on lists} *)
55 let rec function for_all (p: 'a -> bool) (l:list 'a) : bool
56 ensures { result <-> forall x. mem x l -> p x }
60 | Cons x r -> p x && for_all p r
63 let rec function for_some (p: 'a -> bool) (l:list 'a) : bool
64 ensures { result <-> exists x. mem x l /\ p x }
68 | Cons x r -> p x || for_some p r
71 let function mem (eq:'a -> 'a -> bool) (x:'a) (l:list 'a) : bool
72 ensures { result <-> exists y. mem y l /\ eq x y }
85 function elements (l: list 'a) : fset 'a =
88 | Cons x r -> add x (elements r)
92 forall x: 'a, l: list 'a. mem x l <-> Fset.mem x (elements l)
96 (** {2 Nth element of a list} *)
104 let rec function nth (n: int) (l: list 'a) : option 'a =
107 | Cons x r -> if n = 0 then Some x else nth (n - 1) r
117 function nth (n: int) (l: list 'a) : 'a
119 axiom nth_cons_0: forall x:'a, r:list 'a. nth 0 (Cons x r) = x
120 axiom nth_cons_n: forall x:'a, r:list 'a, n:int.
121 n > 0 -> nth n (Cons x r) = nth (n-1) r
134 forall l: list 'a, i: int. i < 0 -> nth i l = None
137 forall l: list 'a, i: int. i >= length l -> nth i l = None
140 forall l: list 'a, i: int. nth i l = None -> i < 0 \/ i >= length l
144 (** {2 Head and tail} *)
151 let function hd (l: list 'a) : option 'a = match l with
156 let function tl (l: list 'a) : option (list 'a) = match l with
167 function hd (l: list 'a) : 'a
169 axiom hd_cons: forall x:'a, r:list 'a. hd (Cons x r) = x
171 function tl (l: list 'a) : list 'a
173 axiom tl_cons: forall x:'a, r:list 'a. tl (Cons x r) = r
177 (** {2 Relation between head, tail, and nth} *)
188 forall l1 l2: list 'a. tl l1 = Some l2 ->
189 forall i: int. i <> -1 -> nth i l2 = nth (i+1) l1
192 forall l: list 'a. nth 0 l = hd l
196 (** {2 Appending two lists} *)
202 let rec function (++) (l1 l2: list 'a) : list 'a =
205 | Cons x1 r1 -> Cons x1 (r1 ++ l2)
209 forall l1 [@induction] l2 l3: list 'a.
210 l1 ++ (l2 ++ l3) = (l1 ++ l2) ++ l3
213 forall l: list 'a. l ++ Nil = l
219 forall l1 [@induction] l2: list 'a. length (l1 ++ l2) = length l1 + length l2
224 forall x: 'a, l1 [@induction] l2: list 'a.
225 mem x (l1 ++ l2) <-> mem x l1 \/ mem x l2
228 forall x: 'a, l: list 'a.
229 mem x l -> exists l1 l2: list 'a. l = l1 ++ Cons x l2
233 module NthLengthAppend
241 forall l1 l2: list 'a, i: int.
242 i < length l1 -> nth i (l1 ++ l2) = nth i l1
245 forall l1 [@induction] l2: list 'a, i: int.
246 length l1 <= i -> nth i (l1 ++ l2) = nth (i - length l1) l2
250 (** {2 Reversing a list} *)
257 let rec function reverse (l: list 'a) : list 'a =
260 | Cons x r -> reverse r ++ Cons x Nil
263 lemma reverse_append:
264 forall l1 l2: list 'a, x: 'a.
265 (reverse (Cons x l1)) ++ l2 = (reverse l1) ++ (Cons x l2)
268 forall l: list 'a, x: 'a.
269 reverse (Cons x l) = reverse l ++ Cons x Nil
273 forall l: list 'a, x: 'a.
274 Cons x (reverse l) = reverse (l ++ Cons x Nil)
276 lemma reverse_reverse:
277 forall l: list 'a. reverse (reverse l) = l
282 forall l: list 'a, x: 'a. mem x l <-> mem x (reverse l)
286 lemma Reverse_length:
287 forall l: list 'a. length (reverse l) = length l
291 (** {2 Reverse append} *)
297 let rec function rev_append (s t: list 'a) : list 'a =
299 | Cons x r -> rev_append r (Cons x t)
305 lemma rev_append_append_l:
306 forall r [@induction] s t: list 'a.
307 rev_append (r ++ s) t = rev_append s (rev_append r t)
312 lemma rev_append_length:
313 forall s [@induction] t: list 'a.
314 length (rev_append s t) = length s + length t
318 lemma rev_append_def:
319 forall r [@induction] s: list 'a. rev_append r s = reverse r ++ s
321 lemma rev_append_append_r:
322 forall r s t: list 'a.
323 rev_append r (s ++ t) = rev_append (rev_append s r) t
333 let rec function combine (x: list 'a) (y: list 'b) : list ('a, 'b)
335 | Cons x0 x, Cons y0 y -> Cons (x0, y0) (combine x y)
341 (** {2 Sorted lists for some order as parameter} *)
349 clone relations.Transitive with
350 type t = t, predicate rel = le, axiom Trans
352 inductive sorted (l: list t) =
356 forall x: t. sorted (Cons x Nil)
358 forall x y: t, l: list t.
359 le x y -> sorted (Cons y l) -> sorted (Cons x (Cons y l))
364 forall x: t, l: list t.
365 (forall y: t. mem y l -> le x y) /\ sorted l <-> sorted (Cons x l)
370 forall l1 [@induction] l2: list t.
371 (sorted l1 /\ sorted l2 /\ (forall x y: t. mem x l1 -> mem y l2 -> le x y))
377 (** {2 Sorted lists of integers} *)
382 clone export Sorted with type t = int, predicate le = (<=), goal Transitive.Trans
390 clone relations.Transitive with
391 type t = t, predicate rel = le, axiom Trans
392 predicate ge (x y: t) = le y x
396 clone Sorted as Incr with type t = t, predicate le = le, goal .
397 clone Sorted as Decr with type t = t, predicate le = ge, goal .
399 predicate compat (s t: list t) =
401 | Cons x _, Cons y _ -> le x y
407 lemma rev_append_sorted_incr:
408 forall s [@induction] t: list t.
409 Incr.sorted (rev_append s t) <->
410 Decr.sorted s /\ Incr.sorted t /\ compat s t
412 lemma rev_append_sorted_decr:
413 forall s [@induction] t: list t.
414 Decr.sorted (rev_append s t) <->
415 Incr.sorted s /\ Decr.sorted t /\ compat t s
419 (** {2 Number of occurrences in a list} *)
426 function num_occ (x: 'a) (l: list 'a) : int =
429 | Cons y r -> (if x = y then 1 else 0) + num_occ x r
431 (** number of occurrences of `x` in `l` *)
433 lemma Num_Occ_NonNeg: forall x:'a, l: list 'a. num_occ x l >= 0
438 forall x: 'a, l: list 'a. mem x l <-> num_occ x l > 0
442 lemma Append_Num_Occ :
443 forall x: 'a, l1 [@induction] l2: list 'a.
444 num_occ x (l1 ++ l2) = num_occ x l1 + num_occ x l2
448 lemma reverse_num_occ :
449 forall x: 'a, l: list 'a.
450 num_occ x l = num_occ x (reverse l)
454 (** {2 Permutation of lists} *)
461 predicate permut (l1: list 'a) (l2: list 'a) =
462 forall x: 'a. num_occ x l1 = num_occ x l2
464 lemma Permut_refl: forall l: list 'a. permut l l
466 lemma Permut_sym: forall l1 l2: list 'a. permut l1 l2 -> permut l2 l1
469 forall l1 l2 l3: list 'a. permut l1 l2 -> permut l2 l3 -> permut l1 l3
472 forall x: 'a, l1 l2: list 'a.
473 permut l1 l2 -> permut (Cons x l1) (Cons x l2)
476 forall x y: 'a, l: list 'a. permut (Cons x (Cons y l)) (Cons y (Cons x l))
480 lemma Permut_cons_append:
481 forall x : 'a, l1 l2 : list 'a.
482 permut (Cons x l1 ++ l2) (l1 ++ Cons x l2)
485 forall l1 l2 l3: list 'a.
486 permut ((l1 ++ l2) ++ l3) (l1 ++ (l2 ++ l3))
489 forall l1 l2 k1 k2 : list 'a.
490 permut l1 k1 -> permut l2 k2 -> permut (l1 ++ l2) (k1 ++ k2)
492 lemma Permut_append_swap:
493 forall l1 l2 : list 'a.
494 permut (l1 ++ l2) (l2 ++ l1)
499 forall x: 'a, l1 l2: list 'a. permut l1 l2 -> mem x l1 -> mem x l2
504 forall l1 [@induction] l2: list 'a. permut l1 l2 -> length l1 = length l2
508 (** {2 List with pairwise distinct elements} *)
515 inductive distinct (l: list 'a) =
516 | distinct_zero: distinct (Nil: list 'a)
517 | distinct_one : forall x:'a. distinct (Cons x Nil)
519 forall x:'a, l: list 'a.
520 not (mem x l) -> distinct l -> distinct (Cons x l)
524 lemma distinct_append:
525 forall l1 [@induction] l2: list 'a.
526 distinct l1 -> distinct l2 -> (forall x:'a. mem x l1 -> not (mem x l2)) ->
536 let rec function prefix (n: int) (l: list 'a) : list 'a =
537 if n <= 0 then Nil else
540 | Cons x r -> Cons x (prefix (n-1) r)
550 let rec function sum (l: list int) : int =
553 | Cons x r -> x + sum r
559 (** {2 Induction on lists} *)
567 (* predicate p (list elt) *)
570 forall p: list 'a -> bool.
572 (forall x:'a. forall l:list 'a. p l -> p (Cons x l)) ->
573 forall l:list 'a. p l
578 (** {2 Maps as lists of pairs} *)
584 function map (f: 'a -> 'b) (l: list 'a) : list 'b =
587 | Cons x r -> Cons (f x) (map f r)
591 (** {2 Generic recursors on lists} *)
597 function fold_left (f: 'b -> 'a -> 'b) (acc: 'b) (l: list 'a) : 'b =
600 | Cons x r -> fold_left f (f acc x) r
605 lemma fold_left_append:
606 forall l1 [@induction] l2: list 'a, f: 'b -> 'a -> 'b, acc : 'b.
607 fold_left f acc (l1++l2) = fold_left f (fold_left f acc l1) l2
615 function fold_right (f: 'a -> 'b -> 'b) (l: list 'a) (acc: 'b) : 'b =
618 | Cons x r -> f x (fold_right f r acc)
623 lemma fold_right_append:
624 forall l1 [@induction] l2: list 'a, f: 'a -> 'b -> 'b, acc : 'b.
625 fold_right f (l1++l2) acc = fold_right f l1 (fold_right f l2 acc)
629 (** {2 Importation of all list theories in one} *)