import Array
Section: 13 Arrays
Section: 13.1 Index Types
第 13 节 数组
第 13.1 节 索引类型
Arrays are built on the class Ix. Here are some quick examples of Ix:
数组建立在类 Ix 之上。这里是 Ix 的几个快速示例:
e1 :: [Int]
e1 = range (0,4)
e2 :: Int
e2 = index (0,4) 2
low,high :: (Int,Int)
low = (1,1)
high = (3,4)
e3 = range (low,high)
e4 = index (low,high) (3,2)
e5 = inRange (low,high) (4,3)
Section: 13.2 Array Creation
第 13.2 节 数组的创建
squares :: Array Int Int
squares = array (1,100) [(i,i*i) | i <- [1..100]]
We can also parameterize this a little:
我们还可以把它稍微参数化:
squares' :: Int -> Array Int Int
squares' n = array (1,n) [(i,i*i) | i <- [1..n]]
e6 :: Int
e6 = squares!6
e7 :: (Int,Int)
e7 = bounds squares
e8 :: Array Int Int
e8 = squares' 10
Here is a function which corresponds to take for lists. It takes an arbitrary slice out of an array.
这里有一个与列表的 take 对应的函数。它从数组中取出任意的一个切片。
atake :: (Ix a) => Array a b -> (a,a) -> Array a b
atake a (l,u) | inRange (bounds a) l && inRange (bounds a) u =
array (l,u) [(i,a!i) | i <- range (l,u)]
| otherwise = error "Subarray out of range"
e9 = atake squares (4,8)
mkArray :: Ix a => (a -> b) -> (a,a) -> Array a b
mkArray f bnds = array bnds [(i,f i) | i <- range bnds]
e10 :: Array Int Int
e10 = mkArray (\i -> i*i) (1,10)
fibs :: Int -> Array Int Int
fibs n = a where
a = array (0,n) ([(0,1), (1,1)] ++
[(i,a!(i-1) + a!(i-2)) | i <- [2..n]])
e11 = atake (fibs 50) (3,10)
wavefront :: Int -> Array (Int,Int) Int
wavefront n = a where
a = array ((1,1),(n,n))
([((1,j),1) | j <- [1..n]] ++
[((i,1),1) | i <- [2..n]] ++
[((i,j),a!(i,j-1) + a!(i-1,j-1) + a!(i-1,j))
| i <- [2..n], j <- [2..n]])
wave = wavefront 20
e12 = atake wave ((1,1),(3,3))
e13 = atake wave ((3,3),(5,5))
Here are some errors in array operations:
这里是数组操作中的几个错误:
e14 :: Int
e14 = wave ! (0,0) -- Out of bounds
arr1 :: Array Int Int
arr1 = array (1,10) [(1,1)] -- No value provided for 2..10
e15,e16 :: Int
e15 = arr1 ! 1 -- works OK
e16 = arr1 ! 2 -- undefined by array
Section: 13.3 Accumulation
第 13.3 节 累加
hist :: (Ix a, Integral b) => (a,a) -> [a] -> Array a b
hist bnds is = accumArray (+) 0 bnds [(i,1) | i <- is, inRange bnds i]
e17 :: Array Char Int
e17 = hist ('a','z') "This counts the frequencies of each lowercase letter"
decades :: (RealFrac a) => a -> a -> [a] -> Array Int Int
decades a b = hist (0,9) . map decade
where
decade x = floor ((x-a) * s)
s = 10 / (b - a)
test1 :: [Float]
test1 = map sin [0..100] -- take the sine of the 0 - 100
e18 = decades 0 1 test1
Section: 13.4 Incremental Updates
第 13.4 节 增量更新
swapRows :: (Ix a, Ix b, Enum b) => a -> a -> Array (a,b) c -> Array (a,b) c
swapRows i i' a = a // ([((i,j),a!(i',j)) | j <- [jLo..jHi]] ++
[((i',j),a!(i,j)) | j <- [jLo..jHi]])
where ((iLo,jLo),(iHi,jHi)) = bounds a
arr2 :: Array (Int,Int) (Int,Int)
arr2 = array ((1,1),(5,5)) [((i,j),(i,j)) | (i,j) <- range ((1,1),(5,5))]
e19 = swapRows 2 3 arr2
Printing the arrays in more readable form makes the results easier to view.
把数组以更易读的格式打印出来,可以更容易地查看结果。
This is a printer for 2d arrays; width is # of columns per element
这是一个二维数组的打印器;width 是每个元素占的列数。
aprint :: (Show b) => Array (Int, Int) b -> Int -> ShowS
aprint a width = shows (bounds a) . showChar '\n' . showRows lx ly where
showRows r c | r > ux = showChar '\n'
showRows r c | c > uy = showChar '\n' . showRows (r+1) ly
showRows r c = showElt (a!(r,c)) . showRows r (c+1)
showElt e = showString (take width (show e ++ repeat ' ')) . showChar ' '
((lx,ly),(ux,uy)) = bounds a
showArray :: (Show b) => Array (Int, Int) b -> Int -> IO ()
showArray a w = putStrLn (aprint a w "")
e20 = showArray e19 6
swapRows' :: (Ix a, Ix b, Enum b) => a -> a -> Array (a,b) c -> Array (a,b) c
swapRows' i i' a = a // [assoc | j <- [jLo..jHi],
assoc <- [((i,j),a!(i',j)),
((i',j),a!(i,j))]]
where ((iLo,jLo),(iHi,jHi)) = bounds a
e21 = showArray (swapRows' 1 5 arr2) 6
Section: 13.5 An example: Matrix Multiplication
第 13.5 节 一个示例:矩阵乘法
matMult :: (Ix a, Ix b, Ix c, Num d) =>
Array (a,b) d -> Array (b,c) d -> Array (a,c) d
matMult x y =
array resultBounds
[((i,j), sum [x!(i,k) * y!(k,j) | k <- range (lj,uj)])
| i <- range (li,ui),
j <- range (lj',uj')]
where
((li,lj),(ui,uj)) = bounds x
((li',lj'),(ui',uj')) = bounds y
resultBounds
| (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
| otherwise = error "matMult: incompatible bounds"
mat1,mat2,mat3,mat4 :: Array (Int,Int) Int
mat1 = array ((0,0),(1,1)) [((0,0),1), ((0,1),0), ((1,0),0), ((1,1),1)]
mat2 = array ((0,0),(1,1)) [((0,0),1), ((0,1),1), ((1,0),1), ((1,1),1)]
mat3 = array ((0,0),(1,1)) [((0,0),1), ((0,1),2), ((1,0),3), ((1,1),4)]
mat4 = array ((0,0),(1,2)) [((0,0),1), ((0,1),2), ((0,2),3),
((1,0),4), ((1,1),5), ((1,2),6)]
e22 = showArray (matMult mat1 mat2) 4
e23 = showArray (matMult mat2 mat3) 4
e24 = showArray (matMult mat1 mat4) 4
e25 = showArray (matMult mat4 mat1) 4
matMult' :: (Ix a, Ix b, Ix c, Num d) =>
Array (a,b) d -> Array (b,c) d -> Array (a,c) d
matMult' x y =
accumArray (+) 0 ((li,lj'),(ui,uj'))
[((i,j), x!(i,k) * y!(k,j))
| i <- range (li,ui),
j <- range (lj',uj'),
k <- range (lj,uj)]
where
((li,lj),(ui,uj)) = bounds x
((li',lj'),(ui',uj')) = bounds y
resultBounds
| (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
| otherwise = error "matMult: incompatible bounds"
e26 = showArray (matMult mat1 mat2) 4
e27 = showArray (matMult mat2 mat3) 4
genMatMul :: (Ix a, Ix b, Ix c) =>
([f] -> g) -> (d -> e -> f) ->
Array (a,b) d -> Array (b,c) e -> Array (a,c) g
genMatMul f g x y =
array ((li,lj'),(ui,uj'))
[((i,j), f [(x!(i,k)) `g` (y!(k,j)) | k <- range (lj,uj)])
| i <- range (li,ui),
j <- range (lj',uj')]
where
((li,lj),(ui,uj)) = bounds x
((li',lj'),(ui',uj')) = bounds y
resultBounds
| (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
| otherwise = error "matMult: incompatible bounds"
e28 = showArray (genMatMul maximum (-) mat2 mat1) 4
e29 = showArray (genMatMul and (==) mat1 mat2) 6
e30 = showArray (genMatMul and (==) mat1 mat1) 6
This is the end of the online supplement
在线补充材料到此结束