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