eedf0587f03b9da33891890eae37ecf9540b2d71
[packages/haskell2010.git] / Data / Array.hs
1 #if __GLASGOW_HASKELL__ >= 701
2 {-# LANGUAGE Trustworthy #-}
3 #endif
4
5 module Data.Array (
6 -- * Immutable non-strict arrays
7 -- $intro
8 module Data.Ix -- export all of Ix
9 , Array -- Array type is abstract
10
11 -- * Array construction
12 , array -- :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
13 , listArray -- :: (Ix a) => (a,a) -> [b] -> Array a b
14 , accumArray -- :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b
15 -- * Accessing arrays
16 , (!) -- :: (Ix a) => Array a b -> a -> b
17 , bounds -- :: (Ix a) => Array a b -> (a,a)
18 , indices -- :: (Ix a) => Array a b -> [a]
19 , elems -- :: (Ix a) => Array a b -> [b]
20 , assocs -- :: (Ix a) => Array a b -> [(a,b)]
21 -- * Incremental array updates
22 , (//) -- :: (Ix a) => Array a b -> [(a,b)] -> Array a b
23 , accum -- :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b
24 -- * Derived arrays
25 , ixmap -- :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a b
26
27 -- * Specification
28
29 -- $code
30 ) where
31
32 import qualified "array" Data.Array as Array
33 import "array" Data.Array hiding (array, (//))
34 import "base" Data.Ix
35
36 {- $intro
37 Haskell provides indexable /arrays/, which may be thought of as functions
38 whose domains are isomorphic to contiguous subsets of the integers.
39 Functions restricted in this way can be implemented efficiently;
40 in particular, a programmer may reasonably expect rapid access to
41 the components. To ensure the possibility of such an implementation,
42 arrays are treated as data, not as general functions.
43
44 Since most array functions involve the class 'Ix', the contents of the
45 module "Data.Ix" are re-exported from "Data.Array" for convenience:
46 -}
47
48 -- SDM: copied documentation for 'array' to remove GHC reference
49
50 -- | Construct an array with the specified bounds and containing values
51 -- for given indices within these bounds.
52 --
53 -- The array is undefined (i.e. bottom) if any index in the list is
54 -- out of bounds. If any
55 -- two associations in the list have the same index, the value at that
56 -- index is undefined (i.e. bottom).
57 --
58 -- Because the indices must be checked for these errors, 'array' is
59 -- strict in the bounds argument and in the indices of the association
60 -- list, but non-strict in the values. Thus, recurrences such as the
61 -- following are possible:
62 --
63 -- > a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i <- [2..100]])
64 --
65 -- Not every index within the bounds of the array need appear in the
66 -- association list, but the values associated with indices that do not
67 -- appear will be undefined (i.e. bottom).
68 --
69 -- If, in any dimension, the lower bound is greater than the upper bound,
70 -- then the array is legal, but empty. Indexing an empty array always
71 -- gives an array-bounds error, but 'bounds' still yields the bounds
72 -- with which the array was constructed.
73 array :: Ix i
74 => (i,i) -- ^ a pair of /bounds/, each of the index type
75 -- of the array. These bounds are the lowest and
76 -- highest indices in the array, in that order.
77 -- For example, a one-origin vector of length
78 -- '10' has bounds '(1,10)', and a one-origin '10'
79 -- by '10' matrix has bounds '((1,1),(10,10))'.
80 -> [(i, e)] -- ^ a list of /associations/ of the form
81 -- (/index/, /value/). Typically, this list will
82 -- be expressed as a comprehension. An
83 -- association '(i, x)' defines the value of
84 -- the array at index 'i' to be 'x'.
85 -> Array i e
86 array = Array.array
87
88 -- SDM copied docs for (//) to remove GHC reference
89
90 -- | Constructs an array identical to the first argument except that it has
91 -- been updated by the associations in the right argument.
92 -- For example, if @m@ is a 1-origin, @n@ by @n@ matrix, then
93 --
94 -- > m//[((i,i), 0) | i <- [1..n]]
95 --
96 -- is the same matrix, except with the diagonal zeroed.
97 --
98 -- Repeated indices in the association list are handled as for 'array':
99 -- the resulting array is undefined (i.e. bottom),
100 (//) :: Ix i => Array i e -> [(i, e)] -> Array i e
101 (//) = (Array.//)
102
103 {- $code
104 > module Array (
105 > module Data.Ix, -- export all of Data.Ix
106 > Array, array, listArray, (!), bounds, indices, elems, assocs,
107 > accumArray, (//), accum, ixmap ) where
108 >
109 > import Data.Ix
110 > import Data.List( (\\) )
111 >
112 > infixl 9 !, //
113 >
114 > data (Ix a) => Array a b = MkArray (a,a) (a -> b) deriving ()
115 >
116 > array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
117 > array b ivs
118 > | any (not . inRange b. fst) ivs
119 > = error "Data.Array.array: out-of-range array association"
120 > | otherwise
121 > = MkArray b arr
122 > where
123 > arr j = case [ v | (i,v) <- ivs, i == j ] of
124 > [v] -> v
125 > [] -> error "Data.Array.!: undefined array element"
126 > _ -> error "Data.Array.!: multiply defined array element"
127 >
128 > listArray :: (Ix a) => (a,a) -> [b] -> Array a b
129 > listArray b vs = array b (zipWith (\ a b -> (a,b)) (range b) vs)
130 >
131 > (!) :: (Ix a) => Array a b -> a -> b
132 > (!) (MkArray _ f) = f
133 >
134 > bounds :: (Ix a) => Array a b -> (a,a)
135 > bounds (MkArray b _) = b
136 >
137 > indices :: (Ix a) => Array a b -> [a]
138 > indices = range . bounds
139 >
140 > elems :: (Ix a) => Array a b -> [b]
141 > elems a = [a!i | i <- indices a]
142 >
143 > assocs :: (Ix a) => Array a b -> [(a,b)]
144 > assocs a = [(i, a!i) | i <- indices a]
145 >
146 > (//) :: (Ix a) => Array a b -> [(a,b)] -> Array a b
147 > a // new_ivs = array (bounds a) (old_ivs ++ new_ivs)
148 > where
149 > old_ivs = [(i,a!i) | i <- indices a,
150 > i `notElem` new_is]
151 > new_is = [i | (i,_) <- new_ivs]
152 >
153 > accum :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)]
154 > -> Array a b
155 > accum f = foldl (\a (i,v) -> a // [(i,f (a!i) v)])
156 >
157 > accumArray :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)]
158 > -> Array a b
159 > accumArray f z b = accum f (array b [(i,z) | i <- range b])
160 >
161 > ixmap :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c
162 > -> Array a c
163 > ixmap b f a = array b [(i, a ! f i) | i <- range b]
164 >
165 > instance (Ix a) => Functor (Array a) where
166 > fmap fn (MkArray b f) = MkArray b (fn . f)
167 >
168 > instance (Ix a, Eq b) => Eq (Array a b) where
169 > a == a' = assocs a == assocs a'
170 >
171 > instance (Ix a, Ord b) => Ord (Array a b) where
172 > a <= a' = assocs a <= assocs a'
173 >
174 > instance (Ix a, Show a, Show b) => Show (Array a b) where
175 > showsPrec p a = showParen (p > arrPrec) (
176 > showString "array " .
177 > showsPrec (arrPrec+1) (bounds a) . showChar ' ' .
178 > showsPrec (arrPrec+1) (assocs a) )
179 >
180 > instance (Ix a, Read a, Read b) => Read (Array a b) where
181 > readsPrec p = readParen (p > arrPrec)
182 > (\r -> [ (array b as, u)
183 > | ("array",s) <- lex r,
184 > (b,t) <- readsPrec (arrPrec+1) s,
185 > (as,u) <- readsPrec (arrPrec+1) t ])
186 >
187 > -- Precedence of the 'array' function is that of application itself
188 > arrPrec = 10
189 -}