985730a871eaf706d8ceb441ab77a6f21326fa90
[haskell-report.git] / report / array.verb
1 %**<title>The Haskell 98 Library Report: Arrays</title>
2 %**~header
3 \section{Arrays}
4 \label{arrays}
5 \index{array}
6
7 \outline{
8 \inputHS{lib-hdrs/Array}
9 }
10
11 \Haskell{} provides indexable {\em arrays}, which may be thought of as
12 functions whose domains are isomorphic to contiguous subsets of the
13 integers.
14 Functions restricted in this way can be
15 implemented efficiently; in particular, a programmer may
16 reasonably expect rapid access to the components.  To ensure
17 the possibility of such an implementation, arrays are treated as data, not as
18 general functions.
19
20 Since most array functions involve the class @Ix@, this module is
21 exported from @Array@ so that modules need not import both @Array@ and
22 @Ix@. 
23
24 \subsection{Array Construction}
25 If @a@ is an index type and @b@ is any type, the type of arrays with
26 indices in @a@ and elements in @b@ is written @Array a b@.\indextycon{Array}
27 An array may be created by the function @array@\indextt{array}.
28 The first argument of @array@ is a pair of {\em bounds}, each of the
29 index type of the array.  These bounds are the lowest and
30 highest indices in the array, in that order.  For example, a
31 one-origin vector of length @10@ has bounds @(1,10)@, and a one-origin @10@
32 by @10@ matrix has bounds @((1,1),(10,10))@.
33
34 The second argument of @array@ is a list of {\em associations}
35 of the form ($index$,~$value$).  Typically, this list will
36 be expressed as a comprehension.  An association @(i, x)@ defines the
37 value of the array at index @i@ to be @x@.  The array is undefined (i.e.~$\bot$) if
38 any index in the list is out of bounds.  If any two associations in the
39 list have the same index, the value at that index is undefined (i.e.~$\bot$).
40 Because the indices must be checked for these errors, @array@ is
41 strict in the bounds argument and in the indices of the association list,
42 but nonstrict in the values.  Thus, recurrences such as the following are
43 possible:
44 \bprog
45 @
46 a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i <- [2..100]])
47 @
48 \eprog
49 Not every index within the bounds of the array need
50 appear in the association list, but the values associated with indices
51 that do not appear will be undefined (i.e.~$\bot$).
52 Figure~\ref{array-examples} shows some examples that use the
53 @array@ constructor.
54
55 \begin{figure}[tb]
56 \begin{outlineenv}\small
57 @
58 -- Scaling an array of numbers by a given number:
59 scale :: (Num a, Ix b) => a -> Array b a -> Array b a
60 scale x a = array b [(i, a!i * x) | i <- range b]
61             where b = bounds a
62
63 -- Inverting an array that holds a permutation of its indices
64 invPerm :: (Ix a) => Array a a -> Array a a
65 invPerm a = array b [(a!i, i) | i <- range b]
66             where b = bounds a
67
68 -- The inner product of two vectors
69 inner :: (Ix a, Num b) => Array a b -> Array a b -> b
70 inner v w = if b == bounds w
71                 then sum [v!i * w!i | i <- range b]
72                 else error "inconformable arrays for inner product"
73             where b = bounds v
74 @
75 \end{outlineenv}
76 \ecaption{Array examples}
77 \label{array-examples}
78 \end{figure}
79
80 The @(!)@\index{""!@@{\tt  {\char'041}}} operator denotes array subscripting.
81 % array subscripting -- if the index lies outside the bounds of the
82 % array, the result is undefined.  
83 The @bounds@\indextt{bounds} function
84 applied to an array returns its bounds.
85 The functions @indices@\indextt{indices}, @elems@\indextt{elems}, and
86 @assocs@,\indextt{assocs} when applied to an array, return lists of
87 the indices, elements, or associations, respectively, in index order.
88 An array may be constructed from a pair of bounds and a list
89 of values in index order using the function @listArray@\indextt{listArray}.
90
91 If, in any dimension, the lower bound is greater than the upper bound,
92 then the array is legal, but empty.  Indexing an empty array always
93 gives an array-bounds error, but @bounds@ still yields the bounds
94 with which the array was constructed.
95
96 \subsubsection{Accumulated Arrays}
97 \index{array!accumulated}
98
99 Another array creation function, @accumArray@,\indextt{accumArray}
100 relaxes the restriction that a given index may appear at most once in
101 the association list, using an {\em accumulating function} which
102 combines the values of associations with the same index.
103 % \cite{nikhil:id-nouveau,wadler:array-primitive}:
104 The first argument of @accumArray@ is the accumulating function; the
105 second is an initial value; the remaining two arguments are a bounds
106 pair and an association list, as for the @array@ function.
107 For example, given a list of values of some index type, @hist@
108 produces a histogram of the number of occurrences of each index within
109 a specified range:
110 \bprog
111 @
112 hist :: (Ix a, Num b) => (a,a) -> [a] -> Array a b
113 hist bnds is = accumArray (+) 0 bnds [(i, 1) | i<-is, inRange bnds i]
114 @
115 \eprog
116 If the accumulating function is strict, then @accumArray@ is
117 strict in the values, as well as the indices, in the
118 association list.  Thus, unlike ordinary arrays,
119 accumulated arrays should not in general be recursive.
120
121 \subsection{Incremental Array Updates}
122 \label{array-update}
123
124 The operator @(//)@\indextt{//} takes an array and a list of pairs and returns
125 an array identical to the left argument except that it has
126 been updated by the associations in the right argument.  (As with
127 the @array@ function, the indices in the association list must
128 be unique for the updated elements to be defined.)  For example,
129 if @m@ is a 1-origin, @n@ by @n@ matrix, then
130 @m//[((i,i), 0) | i <- [1..n]]@ is the same matrix, except with
131 the diagonal zeroed.
132
133 @accum@\indextt{accum} "f" takes an array
134 and an association list and accumulates pairs from the list into
135 the array with the accumulating function "f".  Thus @accumArray@
136 can be defined using @accum@:\nopagebreak[4]
137 \bprog
138 @
139 accumArray f z b = accum f (array b [(i, z) | i <- range b])
140 @
141 \eprogNoSkip
142
143 \subsection{Derived Arrays}
144 \index{array!derived}
145
146 The two functions @fmap@\indextt{fmap} and @ixmap@\indextt{ixmap}
147 derive new arrays from existing ones; they may be
148 thought of as providing function composition on the left and right,
149 respectively, with the mapping that the original array embodies.
150 The @fmap@ function transforms the array values while 
151 @ixmap@ allows for transformations on array indices.
152 Figure~\ref{derived-array-examples} shows some examples.
153
154 \begin{figure}[tb]
155 \begin{outlineenv}\small
156 @
157 -- A rectangular subarray
158 subArray :: (Ix a) => (a,a) -> Array a b -> Array a b
159 subArray bnds = ixmap bnds (\i->i)
160
161 -- A row of a matrix
162 row :: (Ix a, Ix b) => a -> Array (a,b) c -> Array b c
163 row i x = ixmap (l',u') (\j->(i,j)) x where ((_,l'),(_,u')) = bounds x
164
165 -- Diagonal of a matrix (assumed to be square)
166 diag :: (Ix a) => Array (a,a) b -> Array a b
167 diag x = ixmap (l,u) (\i->(i,i)) x
168        where 
169          ((l,_),(u,_)) = bounds x
170
171 -- Projection of first components of an array of pairs
172 firstArray :: (Ix a) => Array a (b,c) -> Array a b
173 firstArray = fmap (\(x,y)->x)
174 @
175 \end{outlineenv}
176 \ecaption{Derived array examples}
177 \label{derived-array-examples}
178 \end{figure}
179
180 \subsection{Library {\tt Array}}
181 \label {Libarray}
182 \inputHS{lib-code/Array}
183 %**~footer