Merge branch 'rac-incomplete-better-trace' into 'master'
[why3.git] / stdlib / list.mlw
blobcb7e61469e883f257e0f1ed6012dbd25bb139608
2 (** {1 Polymorphic Lists} *)
4 (** {2 Basic theory of polymorphic lists} *)
6 module List
8   type list 'a = Nil | Cons 'a (list 'a)
10   let predicate is_nil (l:list 'a)
11     ensures { result <-> l = Nil }
12   =
13     match l with Nil -> true | Cons _ _ -> false end
15 end
17 (** {2 Length of a list} *)
19 module Length
21   use int.Int
22   use List
24   let rec function length (l: list 'a) : int =
25     match l with
26     | Nil      -> 0
27     | Cons _ r -> 1 + length r
28     end
30   lemma Length_nonnegative: forall l: list 'a. length l >= 0
32   lemma Length_nil: forall l: list 'a. length l = 0 <-> l = Nil
34 end
36 (** {2 Membership in a list} *)
38 module Mem
39   use List
41   predicate mem (x: 'a) (l: list 'a) = match l with
42     | Nil      -> false
43     | Cons y r -> x = y \/ mem x r
44     end
46 end
48 (** {2 Quantifiers on lists} *)
50 module Quant
52   use List
53   use Mem
55   let rec function for_all (p: 'a -> bool) (l:list 'a) : bool
56     ensures { result <-> forall x. mem x l -> p x }
57   =
58     match l with
59     | Nil -> true
60     | Cons x r -> p x && for_all p r
61     end
63   let rec function for_some (p: 'a -> bool) (l:list 'a) : bool
64     ensures { result <-> exists x. mem x l /\ p x }
65   =
66     match l with
67     | Nil -> false
68     | Cons x r -> p x || for_some p r
69     end
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 }
73   =
74     for_some (eq x) l
76 end
79 module Elements
81   use set.Fset
82   use List
83   use Mem
85   function elements (l: list 'a) : fset 'a =
86     match l with
87     | Nil -> empty
88     | Cons x r -> add x (elements r)
89     end
91   lemma elements_mem:
92     forall x: 'a, l: list 'a. mem x l <-> Fset.mem x (elements l)
94 end
96 (** {2 Nth element of a list} *)
98 module Nth
100   use List
101   use option.Option
102   use int.Int
104   let rec function nth (n: int) (l: list 'a) : option 'a =
105     match l with
106     | Nil      -> None
107     | Cons x r -> if n = 0 then Some x else nth (n - 1) r
108     end
112 module NthNoOpt
114   use List
115   use int.Int
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
125 module NthLength
127   use int.Int
128   use option.Option
129   use List
130   use export Nth
131   use export Length
133   lemma nth_none_1:
134      forall l: list 'a, i: int. i < 0 -> nth i l = None
136   lemma nth_none_2:
137      forall l: list 'a, i: int. i >= length l -> nth i l = None
139   lemma nth_none_3:
140      forall l: list 'a, i: int. nth i l = None -> i < 0 \/ i >= length l
144 (** {2 Head and tail} *)
146 module HdTl
148   use List
149   use option.Option
151   let function hd (l: list 'a) : option 'a = match l with
152     | Nil      -> None
153     | Cons h _ -> Some h
154   end
156   let function tl (l: list 'a) : option (list 'a) = match l with
157     | Nil      -> None
158     | Cons _ t -> Some t
159   end
163 module HdTlNoOpt
165   use List
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} *)
179 module NthHdTl
181   use int.Int
182   use option.Option
183   use List
184   use Nth
185   use HdTl
187   lemma Nth_tl:
188     forall l1 l2: list 'a. tl l1 = Some l2 ->
189     forall i: int. i <> -1 -> nth i l2 = nth (i+1) l1
191   lemma Nth0_head:
192     forall l: list 'a. nth 0 l = hd l
196 (** {2 Appending two lists} *)
198 module Append
200   use List
202   let rec function (++) (l1 l2: list 'a) : list 'a =
203     match l1 with
204     | Nil -> l2
205     | Cons x1 r1 -> Cons x1 (r1 ++ l2)
206     end
208   lemma Append_assoc:
209     forall l1 [@induction] l2 l3: list 'a.
210     l1 ++ (l2 ++ l3) = (l1 ++ l2) ++ l3
212   lemma Append_l_nil:
213     forall l: list 'a. l ++ Nil = l
215   use Length
216   use int.Int
218   lemma Append_length:
219     forall l1 [@induction] l2: list 'a. length (l1 ++ l2) = length l1 + length l2
221   use Mem
223   lemma mem_append:
224     forall x: 'a, l1 [@induction] l2: list 'a.
225     mem x (l1 ++ l2) <-> mem x l1 \/ mem x l2
227   lemma mem_decomp:
228     forall x: 'a, l: list 'a.
229     mem x l -> exists l1 l2: list 'a. l = l1 ++ Cons x l2
233 module NthLengthAppend
235   use int.Int
236   use List
237   use export NthLength
238   use export Append
240   lemma nth_append_1:
241     forall l1 l2: list 'a, i: int.
242     i < length l1 -> nth i (l1 ++ l2) = nth i l1
244   lemma nth_append_2:
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} *)
252 module Reverse
254   use List
255   use Append
257   let rec function reverse (l: list 'a) : list 'a =
258     match l with
259     | Nil      -> Nil
260     | Cons x r -> reverse r ++ Cons x Nil
261     end
263   lemma reverse_append:
264     forall l1 l2: list 'a, x: 'a.
265     (reverse (Cons x l1)) ++ l2 = (reverse l1) ++ (Cons x l2)
267   lemma reverse_cons:
268     forall l: list 'a, x: 'a.
269     reverse (Cons x l) = reverse l ++ Cons x Nil
272   lemma cons_reverse:
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
279   use Mem
281   lemma reverse_mem:
282     forall l: list 'a, x: 'a. mem x l <-> mem x (reverse l)
284   use Length
286   lemma Reverse_length:
287     forall l: list 'a. length (reverse l) = length l
291 (** {2 Reverse append} *)
293 module RevAppend
295   use List
297   let rec function rev_append (s t: list 'a) : list 'a =
298     match s with
299     | Cons x r -> rev_append r (Cons x t)
300     | Nil -> t
301     end
303   use Append
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)
309   use int.Int
310   use Length
312   lemma rev_append_length:
313     forall s [@induction] t: list 'a.
314       length (rev_append s t) = length s + length t
316   use Reverse
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
327 (** {2 Zip} *)
329 module Combine
331   use List
333   let rec function combine (x: list 'a) (y: list 'b) : list ('a, 'b)
334   = match x, y with
335     | Cons x0 x, Cons y0 y -> Cons (x0, y0) (combine x y)
336     | _ -> Nil
337     end
341 (** {2 Sorted lists for some order as parameter} *)
343 module Sorted
345   use List
347   type t
348   predicate le t t
349   clone relations.Transitive with
350     type t = t, predicate rel = le, axiom Trans
352   inductive sorted (l: list t) =
353     | Sorted_Nil:
354         sorted Nil
355     | Sorted_One:
356         forall x: t. sorted (Cons x Nil)
357     | Sorted_Two:
358         forall x y: t, l: list t.
359         le x y -> sorted (Cons y l) -> sorted (Cons x (Cons y l))
361   use Mem
363   lemma sorted_mem:
364     forall x: t, l: list t.
365     (forall y: t. mem y l -> le x y) /\ sorted l <-> sorted (Cons x l)
367   use Append
369   lemma sorted_append:
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))
372     <->
373     sorted (l1 ++ l2)
377 (** {2 Sorted lists of integers} *)
379 module SortedInt
381   use int.Int
382   clone export Sorted with type t = int, predicate le = (<=), goal Transitive.Trans
386 module RevSorted
388   type t
389   predicate le t t
390   clone relations.Transitive with
391     type t = t, predicate rel = le, axiom Trans
392   predicate ge (x y: t) = le y x
394   use List
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) =
400     match s, t with
401     | Cons x _, Cons y _ -> le x y
402     | _, _ -> true
403     end
405   use RevAppend
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} *)
421 module NumOcc
423   use int.Int
424   use List
426   function num_occ (x: 'a) (l: list 'a) : int =
427     match l with
428     | Nil      -> 0
429     | Cons y r -> (if x = y then 1 else 0) + num_occ x r
430     end
431   (** number of occurrences of `x` in `l` *)
433   lemma Num_Occ_NonNeg: forall x:'a, l: list 'a. num_occ x l >= 0
435   use Mem
437   lemma Mem_Num_Occ :
438     forall x: 'a, l: list 'a. mem x l <-> num_occ x l > 0
440   use Append
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
446   use Reverse
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} *)
456 module Permut
458   use NumOcc
459   use List
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
468   lemma Permut_trans:
469     forall l1 l2 l3: list 'a. permut l1 l2 -> permut l2 l3 -> permut l1 l3
471   lemma Permut_cons:
472     forall x: 'a, l1 l2: list 'a.
473     permut l1 l2 -> permut (Cons x l1) (Cons x l2)
475   lemma Permut_swap:
476     forall x y: 'a, l: list 'a. permut (Cons x (Cons y l)) (Cons y (Cons x l))
478   use Append
480   lemma Permut_cons_append:
481     forall x : 'a, l1 l2 : list 'a.
482     permut (Cons x l1 ++ l2) (l1 ++ Cons x l2)
484   lemma Permut_assoc:
485     forall l1 l2 l3: list 'a.
486     permut ((l1 ++ l2) ++ l3) (l1 ++ (l2 ++ l3))
488   lemma Permut_append:
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)
496   use Mem
498   lemma Permut_mem:
499     forall x: 'a, l1 l2: list 'a. permut l1 l2 -> mem x l1 -> mem x l2
501   use Length
503   lemma Permut_length:
504     forall l1 [@induction] l2: list 'a. permut l1 l2 -> length l1 = length l2
508 (** {2 List with pairwise distinct elements} *)
510 module Distinct
512   use List
513   use Mem
515   inductive distinct (l: list 'a) =
516     | distinct_zero: distinct (Nil: list 'a)
517     | distinct_one : forall x:'a. distinct (Cons x Nil)
518     | distinct_many:
519         forall x:'a, l: list 'a.
520         not (mem x l) -> distinct l -> distinct (Cons x l)
522   use Append
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)) ->
527     distinct (l1 ++ l2)
531 module Prefix
533   use List
534   use int.Int
536   let rec function prefix (n: int) (l: list 'a) : list 'a =
537     if n <= 0 then Nil else
538     match l with
539     | Nil -> Nil
540     | Cons x r -> Cons x (prefix (n-1) r)
541     end
545 module Sum
547   use List
548   use int.Int
550   let rec function sum (l: list int) : int =
551     match l with
552     | Nil -> 0
553     | Cons x r -> x + sum r
554     end
559 (** {2 Induction on lists} *)
561 module Induction
563   use List
565   (* type elt *)
567   (* predicate p (list elt) *)
569   axiom Induction:
570     forall p: list 'a -> bool.
571     p (Nil: list 'a) ->
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} *)
580 module Map
582   use List
584   function map (f: 'a -> 'b) (l: list 'a) : list 'b =
585     match l with
586     | Nil      -> Nil
587     | Cons x r -> Cons (f x) (map f r)
588     end
591 (** {2 Generic recursors on lists} *)
593 module FoldLeft
595   use List
597   function fold_left (f: 'b -> 'a -> 'b) (acc: 'b) (l: list 'a) : 'b =
598     match l with
599     | Nil      -> acc
600     | Cons x r -> fold_left f (f acc x) r
601     end
603   use Append
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
611 module FoldRight
613   use List
615   function fold_right (f: 'a -> 'b -> 'b) (l: list 'a) (acc: 'b) : 'b =
616     match l with
617     | Nil      -> acc
618     | Cons x r -> f x (fold_right f r acc)
619     end
621   use Append
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} *)
631 module ListRich
633   use export List
634   use export Length
635   use export Mem
636   use export Nth
637   use export HdTl
638   use export NthHdTl
639   use export Append
640   use export Reverse
641   use export RevAppend
642   use export NumOcc
643   use export Permut