Haskell修复---使用索引进行映射

时间:2011-06-05 10:50:25

标签: arrays haskell repa

想象一下,我想在一个数组上映射一个函数,但该函数的类型不仅仅是     a -> b 但     a -> Int -> b 即该函数也采用索引。我该怎么做?

3 个答案:

答案 0 :(得分:8)

简短回答,请使用traverse

更长的例子:

import qualified Data.Array.Repa as A
import qualified Data.Vector.Unboxed as U

arr1 :: A.Array A.DIM2 Double
arr1 = A.fromVector (A.Z A.:. 2 A.:. 3) $ U.fromList [1::Double,2,3,4,5,6]

arr2 :: A.Array A.DIM2 Double
arr2 = A.traverse arr1 id (\lf i@(A.Z A.:. r A.:. c) -> 
                  (lf i) + (fromIntegral r) + (fromIntegral c))  

arr1是一个2x3的矩阵。 traverse是一个函数,它接受(1)原始数组,(2)用于将源索引映射到目标索引的函数,以及(3)给出(i)查找函数到原始数组中的函数和(ii)返回新值的索引。

所以这里arr2通过添加特定条目的行索引和列索引来修改每个原始元素。

答案 1 :(得分:8)

很好的问题,Repa tutorial没有记录,所以我用a new section on traversals更新了它。

特别是,traverse可以让您:

  • 更改输出数组的形状
  • 索引任何eleemnt
  • 观察当前元素

意思是你可以做以下事情:

将所有元素替换为行索引

> traverse a id (\_ (Z :. i :. j :. k) -> i) 
[0,0,0,0,0,0,0,0,0
,1,1,1,1,1,1,1,1,1
,2,2,2,2,2,2,2,2,2]

将一个元素乘以其行

> traverse a id (\f (Z :. i :. j :. k) -> f (Z :. i :. j :. k) * i) 
[0,0,0,0,0,0,0,0,0
,10,11,12,13,14,15,16,17,18
,38,40,42,44,46,48,50,52,54]

等等。 <{1}} 非常功能强大,并且神奇地并行。

高级:并行图像去饱和

Example from the Repa tutorial

答案 2 :(得分:1)

使用zipWith

zipWith (\idx ele -> if even idx then div ele 2 else ele) [0..] xs