10

想象一下,我想将一个函数映射到一个数组上,但该函数不仅有一个类型, a -> b 而且 a -> Int -> b 该函数还需要一个索引。我怎么做?

4

3 回答 3

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通过添加该特定条目的行和列索引来修改每个原始元素。

于 2011-06-05T11:15:31.557 回答
8

好问题,它没有记录在Repa 教程中,所以我用一个关于 traversals 的新部分对其进行了更新。

特别是,traverse让您:

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

这意味着您可以执行以下操作:

用它们的行索引替换所有元素

> 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]

等等。travese厉害,而且还神奇的平行。

高级:并行图像去饱和

Repa 教程中的示例

于 2011-06-05T14:45:54.403 回答
2

使用 zipWith

zipWith (\idx ele -> if even idx then div ele 2 else ele) [0..] xs
于 2017-07-01T17:23:08.637 回答