Evg*_*M86 7 arrays indexing haskell fold repa
在GNU Octave中这段代码 -
[e, ix] = min(X);
Run Code Online (Sandbox Code Playgroud)
将返回最小元素及其位置.你如何修复任意二元函数?
这就是我想出的:
min x = z $ foldl' f (e,0,0) es
where
(e:es) = toList x
f (a,ix,r) b = let ix' = ix+1 in if a < b then (a,ix',r) else (b,ix',ix')
z (a,ix,r) = (a,r)
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我们将repa 1D矩阵转换为list并使用foldl'(来自Data.List)和两个累加器 - 一个用于计算迭代(ix),另一个用于保存min元素(r)的位置.但是使用repa的重点是使用数组,而不是列表!
在repa中,Array类型有两个折叠(foldS和foldP) - 但是它们只能取类型函数(a - > a - > a) - 意思是,我不能将带累加器的元组传递给它.还有遍历,原则上可以将1D数组减少为标量数组:
min x = traverse x to0D min
where
to0D (Z:.i) = Z
min f (Z) = ??? -- how to get elements for comparison?
Run Code Online (Sandbox Code Playgroud)
首先想到的是
[f (Z:.i) | i <- [1..n]], where n = (\(Z:.i) -> i) $ extent x
Run Code Online (Sandbox Code Playgroud)
但这也会将数组转换为列表,而不是在数组上进行计算.
我不是 Repa 方面的专家,但这似乎适用于一维数组。它可能可以适应其他尺寸。
import Data.Array.Repa
indexed arr = traverse arr id (\src idx@(Z :. i) -> (src idx, i))
minimize arr = foldP f h t
where
(Z :. n) = extent arr
arr' = indexed arr
h = arr' ! (Z :. 0)
t = extract (Z :. 1) (Z :. (n-1)) arr'
f min@(valMin, iMin) x@(val, i) | val < valMin = x
| otherwise = min
Run Code Online (Sandbox Code Playgroud)