diff -r 16cc1161ad7f -r db0c70767d86 src/HOL/Library/IArray.thy --- a/src/HOL/Library/IArray.thy Wed Jul 18 20:51:21 2018 +0200 +++ b/src/HOL/Library/IArray.thy Wed Jul 18 20:51:22 2018 +0200 @@ -1,5 +1,7 @@ (* Title: HOL/Library/IArray.thy Author: Tobias Nipkow, TU Muenchen + Author: Jose Divasón + Author: Jesús Aransay *) section \Immutable Arrays with Code Generation\ @@ -32,15 +34,11 @@ qualified definition length :: "'a iarray \ nat" where [simp]: "length as = List.length (IArray.list_of as)" -qualified primrec all :: "('a \ bool) \ 'a iarray \ bool" where -"all p (IArray as) \ (\a \ set as. p a)" +qualified definition all :: "('a \ bool) \ 'a iarray \ bool" where +[simp]: "all p as \ (\a \ set (list_of as). p a)" -qualified primrec exists :: "('a \ bool) \ 'a iarray \ bool" where -"exists p (IArray as) \ (\a \ set as. p a)" - -lemma list_of_code [code]: -"IArray.list_of as = map (\n. as !! n) [0 ..< IArray.length as]" -by (cases as) (simp add: map_nth) +qualified definition exists :: "('a \ bool) \ 'a iarray \ bool" where +[simp]: "exists p as \ (\a \ set (list_of as). p a)" lemma of_fun_nth: "IArray.of_fun f n !! i = f i" if "i < n" @@ -79,10 +77,18 @@ "rel_iarray r as bs = list_all2 r (IArray.list_of as) (IArray.list_of bs)" by (cases as, cases bs) auto +lemma list_of_code [code]: + "IArray.list_of as = map (\n. as !! n) [0 ..< IArray.length as]" + by (cases as) (simp add: map_nth) + lemma [code]: "HOL.equal as bs \ HOL.equal (IArray.list_of as) (IArray.list_of bs)" by (cases as, cases bs) (simp add: equal) +lemma [code]: + "IArray.all p = Not \ IArray.exists (Not \ p)" + by (simp add: fun_eq_iff) + context term_syntax begin @@ -107,7 +113,7 @@ by simp qualified primrec sub' :: "'a iarray \ integer \ 'a" where - "sub' (as, n) = IArray.list_of as ! nat_of_integer n" + "sub' (as, n) = as !! nat_of_integer n" lemma [code]: "IArray.sub' (IArray as, n) = as ! nat_of_integer n" @@ -128,6 +134,37 @@ "IArray.length as = nat_of_integer (IArray.length' as)" by simp +qualified definition exists_upto :: "('a \ bool) \ integer \ 'a iarray \ bool" where + [simp]: "exists_upto p k as \ (\l. 0 \ l \ l < k \ p (sub' (as, l)))" + +lemma exists_upto_of_nat: + "exists_upto p (of_nat n) as \ (\m (if k \ 0 then False else + let l = k - 1 in p (sub' (as, l)) \ exists_upto p l as)" +proof (cases "k \ 1") + case False + then show ?thesis + by (auto simp add: not_le discrete) +next + case True + then have less: "k \ 0 \ False" + by simp + define n where "n = nat_of_integer (k - 1)" + with True have k: "k - 1 = of_nat n" "k = of_nat (Suc n)" + by simp_all + show ?thesis unfolding less Let_def k(1) unfolding k(2) exists_upto_of_nat + using less_Suc_eq by auto +qed + +lemma [code]: + "IArray.exists p as \ exists_upto p (length' as) as" + including integer.lifting by (simp, transfer) + (auto, metis in_set_conv_nth less_imp_of_nat_less nat_int of_nat_0_le_iff) + end @@ -148,4 +185,43 @@ | constant IArray.sub' \ (SML) "Vector.sub" | constant IArray.length' \ (SML) "Vector.length" + +subsection \Code Generation for Haskell\ + +text \We map @{typ "'a iarray"}s in Isabelle/HOL to @{text Data.Array.IArray.array} + in Haskell. Performance mapping to @{text Data.Array.Unboxed.Array} and + @{text Data.Array.Array} is similar.\ + +code_printing + code_module "IArray" \ (Haskell) \ + import Prelude (Bool(True, False), not, Maybe(Nothing, Just), + Integer, (+), (-), (<), fromInteger, toInteger, map, seq, (.)); + import qualified Prelude; + import qualified Data.Array.IArray; + import qualified Data.Array.Base; + import qualified Data.Ix; + + newtype IArray e = IArray (Data.Array.IArray.Array Integer e); + + tabulate :: (Integer, (Integer -> e)) -> IArray e; + tabulate (k, f) = IArray (Data.Array.IArray.array (0, k - 1) (map (\i -> let fi = f i in fi `seq` (i, fi)) [0..k - 1])); + + of_list :: [e] -> IArray e; + of_list l = IArray (Data.Array.IArray.listArray (0, (toInteger . Prelude.length) l - 1) l); + + sub :: (IArray e, Integer) -> e; + sub (IArray v, i) = v `Data.Array.Base.unsafeAt` fromInteger i; + + length :: IArray e -> Integer; + length (IArray v) = toInteger (Data.Ix.rangeSize (Data.Array.IArray.bounds v));\ + +code_reserved Haskell IArray_Impl + +code_printing + type_constructor iarray \ (Haskell) "IArray.IArray _" +| constant IArray \ (Haskell) "IArray.of'_list" +| constant IArray.tabulate \ (Haskell) "IArray.tabulate" +| constant IArray.sub' \ (Haskell) "IArray.sub" +| constant IArray.length' \ (Haskell) "IArray.length" + end