(* Title: Haskell Library
Author: Ricardo Peņa, Javier de Dios
Copyright: May 2008, Universidad Complutense de Madrid
*)
header {* Useful functions and theorems from the Haskell Library or Prelude *}
theory HaskellLib
imports Main
begin
text{* Function {\sl mapAccumL} is a powerful combination of {\sl map} and
{\sl foldl}. Functions {\sl unzip3} and {\sl unzip} are respectively the
inverse of {\sl zip3} and {\sl zip}. *}
consts
mapAccumL :: "('a => 'b => 'a × 'c) => 'a => 'b list => 'a × 'c list"
zipWith :: "('a => 'b => 'c) => 'a list => 'b list => 'c list "
unzip3 :: "('a × 'b× 'c) list => 'a list × 'b list × 'c list"
unzip :: "('a × 'b) list => 'a list × 'b list"
primrec
"mapAccumL f s [] = (s,[])"
"mapAccumL f s (x#xs) = (let (s',y) = f s x;
(s'',ys) = mapAccumL f s' xs
in (s'',y#ys))"
text {* Some lemmas about mapAccumL *}
lemma mapAccumL_non_empty:
"[| (s'',ys) = mapAccumL f s xs;
xs = x#xx
|] ==> (∃ s' y ys'.
(s',y) = f s x
∧ ys = y # ys')"
apply clarify
apply (unfold mapAccumL.simps)
apply (rule_tac x="fst (f s x)" in exI)
apply (rule_tac x="snd (f s x)" in exI)
apply (rule_tac x="snd (mapAccumL f (fst (f s x)) xx)" in exI)
apply (rule conjI)
apply simp
apply (case_tac "f s x",simp)
by (case_tac "mapAccumL f a xx",simp)
lemma mapAccumL_non_empty2:
"[| (s'',ys) = mapAccumL f s xs;
xs = x#xx
|] ==> (∃ s' y ys'.
(s',y) = f s x
∧ (s'',ys') = mapAccumL f s' xx
∧ ys = y # ys')"
apply clarify
apply (unfold mapAccumL.simps)
apply (rule_tac x="fst (f s x)" in exI)
apply (rule_tac x="snd (f s x)" in exI)
apply (rule_tac x="snd (mapAccumL f (fst (f s x)) xx)" in exI)
apply (rule conjI)
apply simp
apply (rule conjI)
apply (case_tac "f s x") apply (simp)
apply (case_tac "mapAccumL f a xx")
apply (simp)
apply (case_tac "f s x") apply (simp)
apply (case_tac "mapAccumL f a xx")
apply simp
done
axioms mapAccumL_non_empty3:
"[| (s'',ys) = mapAccumL f s xs;
0<length xs
|] ==> (∃ s' y ys'.
(s',y) = f s (xs!0)
∧ (s'',ys') = mapAccumL f s' (tl xs))"
axioms mapAccumL_two_elements:
"[| (s3,ys) = mapAccumL f s xs;
xs = x1#x2#xx
|] ==> (∃ s1 s2 y1 y2 ys3.
(s1,y1) = f s x1
∧ (s2,y2) = f s1 x2
∧ (s3,ys3) = mapAccumL f s2 xx
∧ ys = y1#y2#ys3)"
axioms mapAccumL_split:
"[| (s2,ys) = mapAccumL f s xs;
xs1 @ xs2=xs
|] ==> (∃ s1 ys1 ys2 .
(s1,ys1) = mapAccumL f s xs1
∧ (s2,ys2) = mapAccumL f s1 xs2
∧ ys = ys1 @ ys2)"
axioms mapAccumL_one_more:
"[| (s1,ys) = mapAccumL f s xs;
(s2,y) = f s1 x
|] ==> (s2,ys@[y]) = mapAccumL f s (xs@[x])"
text {* Some integer arithmetic lemmas *}
lemma sum_nat:
"[| (x1::nat)=x2;(y1::nat)=y2|] ==> x1+y1=x2+y2"
apply arith
done
axioms sum_substract:
"(x::nat)-y+(z-x)=z-y"
axioms additions1:
"[| i< m; Suc m + n ≤ l|] ==>
m - i < nat (int l - 1) - n + 1 - (nat (int l - 1) - Suc m - n + 1)"
axioms additions2:
"[| i< m; Suc m + n ≤ l|] ==>
nat (int l - 1) - m + (m - Suc i) = nat (int l - 1) - Suc m + (m - i)"
axioms additions3:
"[| i< m; Suc m + n ≤ l|] ==>
nat (int l - 1)- Suc (m + n)+(m - i)=nat (int l - 1)-(m + n)+(m - Suc i)"
axioms additions4:
"[| Suc m + n ≤ l|] ==>
nat (int l - 1) - m = Suc (nat (int l - 1) - Suc m)"
axioms additions5:
"[| Suc m + n ≤ l|] ==>
Suc (nat (int l - 1) - Suc (m + n)) = nat (int l - 1 - int n - int m)"
axioms additions6:
"[| Suc m + n ≤ l|] ==>
n + (nat (int l - 1) - Suc (m + n)) < nat (int l - 1)"
text {* Some lemmas about lists *}
lemma list_non_empty:
"0<length xs ==> (∃ y ys . xs = y # ys)"
apply auto
apply (insert neq_Nil_conv [of xs])
by simp
axioms drop_nth:
"n < length xs ==> (∃ y ys . drop n xs = y#ys ∧ xs!n = y)"
axioms drop_nth3:
"n < length xs ==> drop n xs = (xs!n) # drop (Suc n) xs"
axioms drop_take_Suc:
"xs=(take n xs)@(z#zs) ==> drop (Suc n) xs=zs"
axioms drop_nth2:
"[| n<length xs; drop n xs = ys|]
==> ys = xs!n # tl ys "
axioms drop_append2:
"[| drop n xs = zs1 @ ys1 @ ys2 @ zs2 @ rest;
drop (m-n) (zs1 @ ys1 @ ys2 @ zs2)= ys1 @ rest'
|] ==>
drop (m+length ys1-n) (zs1 @ ys1 @ ys2 @ zs2) = ys2 @ zs2"
axioms drop_append3:
"[| drop n xs = xs1 @ rest;
drop (m-n) xs1 = ys1 @ ys2
|] ==>
drop m xs = ys1 @ ys2 @ rest"
lemma nth_via_drop_append: "drop n xs = (y#ys)@zs ==> xs!n = y"
apply (induct xs arbitrary: n, simp)
by(simp add:drop_Cons nth_Cons split:nat.splits)
lemma drop_Suc_append:
"drop n xs = (y#ys)@zs ==> drop (Suc n) xs = ys@zs"
apply (induct xs arbitrary: n,simp)
apply (simp add:drop_Cons)
by (simp split:nat.splits)
lemma nth_via_drop_append_2: "drop n xs = ((y # ys) @ ws @ zs) @ ms ==> xs!n = y"
apply (induct xs arbitrary: n, simp)
by(simp add:drop_Cons nth_Cons split:nat.splits)
lemma drop_Suc_append_2:
"drop n xs = ((y # ys) @ ws @ zs) @ ms ==> drop (Suc n) xs = ys @ ws @ zs @ ms"
apply (induct xs arbitrary: n,simp)
apply (simp add:drop_Cons)
by (simp split:nat.splits)
axioms drop_append_length:
"drop n xs = [] @ ys @ zs @ ms ==> drop (n + length ys) xs = zs @ ms"
axioms take_length:
"n ≤ length xs ==> n = length (take n xs)"
axioms take_append2:
"n<length xs ==> x # take n xs = take n (x # xs) @ [(x # xs)!n]"
axioms take_append3:
"Suc n ≤ length xs ==> take (Suc n) xs = take n xs @ [xs!n]"
axioms concat1:
"xs @ y # ys = (xs @ [y]) @ ys"
axioms concat2:
"xs1 = xs2 ==> xs1 @ ys = xs2 @ ys "
axioms upt_length:
"n ≤ m ==> length [n..<m]=m-n"
text {* Some lemmas about finite maps *}
axioms map_of_distinct:
"[| distinct (map fst xys);
l < length xys;
(x,y) = xys ! l
|] ==> map_of xys x = Some y"
axioms map_of_distinct2:
"map_of xys x = Some y
==> (∃ l . l < length xys ∧ (x,y) = xys ! l)"
axioms map_upds_nth:
"i < m-n ==> (A([n..<m] [\<mapsto>] xs)) (n+i) = Some (xs ! i)"
-- "The unzip3 function of Haskell library"
primrec
"unzip3 [] = ([],[],[])"
"unzip3 (tup#tups) = (let (xs,ys,zs) = unzip3 tups;
(x,y,z) = tup
in (x#xs,y#ys,z#zs))"
axioms unzip3_length:
"unzip3 xs = (ys1,ys2,ys3) ==> length ys1 = length ys2"
primrec
"unzip [] = ([],[])"
"unzip (tup#tups) = (let (xs,ys) = unzip tups;
(x,y) = tup
in (x#xs,y#ys))"
primrec
"zipWith f (x#xs) yy = (case yy of
[] => []
| y#ys => f x y # zipWith f xs ys)"
"zipWith f [] yy = []"
axioms zipWith_length:
"length (zipWith f xs ys) = min (length xs) (length ys)"
-- "The Haskell sum type Either"
datatype ('a,'b) Either = Left 'a | Right 'b
-- "insertion sort for list of strings"
constdefs
leString :: "string => string => bool"
"leString s1 s2 == True"
(*
primrec
"leList [] ts = True"
"leList (s#ss) ts = (case ts of [] => False
| t#tt => (s < t ∨ s=t ∧ leList ss tt))"
*)
consts
ins :: "string => string list => string list"
primrec
"ins s [] = [s]"
"ins s (s'#ss) = (if leString s s' then s#s'#ss
else s'# ins s ss)"
fun sort :: "string list => string list"
where
"sort ss = foldr ins ss []"
fun subList :: "'a list => 'a list => bool"
where
"subList xs ys = (∃ hs ts. ys = hs @ xs @ ts)"
end
lemma mapAccumL_non_empty:
[| (s'', ys) = mapAccumL f s xs; xs = x # xx |]
==> ∃s' y ys'. (s', y) = f s x ∧ ys = y # ys'
lemma mapAccumL_non_empty2:
[| (s'', ys) = mapAccumL f s xs; xs = x # xx |]
==> ∃s' y ys'. (s', y) = f s x ∧ (s'', ys') = mapAccumL f s' xx ∧ ys = y # ys'
lemma sum_nat:
[| x1.0 = x2.0; y1.0 = y2.0 |] ==> x1.0 + y1.0 = x2.0 + y2.0
lemma list_non_empty:
0 < length xs ==> ∃y ys. xs = y # ys
lemma nth_via_drop_append:
drop n xs = (y # ys) @ zs ==> xs ! n = y
lemma drop_Suc_append:
drop n xs = (y # ys) @ zs ==> drop (Suc n) xs = ys @ zs
lemma nth_via_drop_append_2:
drop n xs = ((y # ys) @ ws @ zs) @ ms ==> xs ! n = y
lemma drop_Suc_append_2:
drop n xs = ((y # ys) @ ws @ zs) @ ms ==> drop (Suc n) xs = ys @ ws @ zs @ ms