如何按 Repa 中的索引谓词进行过滤

How to filter by predicate on index in Repa

我有两个 Repa 数组 a1a2,我想消除 a2 中的所有元素,这些元素在 a1 中的相应索引高于 a一定的门槛。例如:

import qualified Data.Array.Repa as R -- for Repa
import Data.Array.Repa (Z (..), (:.)(..))


a1 = R.fromFunction (Z :. 4) $ \(Z :. x) -> [8, 15, 9, 14] ! x
a2 = R.fromFunction (Z :. 4) $ \(Z :. x) -> [0, 1, 2, 3] ! x
threshold = 10
desired = R.fromFunction (Z :. 2) $ \(Z :. x) -> [0, 2] ! x
-- 15 and 14 are above the threshold, 10

一种方法是使用 selectP,但我想避免使用它,因为它会计算数组,如果可能的话,我希望我的数组保持延迟形式。

另一种方法是使用 repa-array,但 stack solver 似乎不知道如何使用解析器导入此库 nightly-2017-04-10

您可以使用 zip 构建对列表,然后通过类型为 (Int,Int) -> Bool 的谓词函数 filter 构建对列表,最后提取对的第一个或第二个元素(取决于分别使用 map fstmap snd。您需要的一切都在 Prelude 中。

我希望这是足够的信息,以便您可以自己将各个部分拼凑起来。如果有疑问,请查看我提到的函数的类型签名。

看待这个问题的一种方法是,为了创建 Repa 数组,您需要知道创建时数组的大小 (extent)(例如 fromFunction) ,但是,在过滤操作的情况下,如果不应用阈值谓词,就无法知道 repa 中结果数组的大小,本质上是计算结果数组的值。

另一种看待它的方式是,D延迟数组是一个从索引到值的简单函数,适用于大多数操作。但是对于过滤,当您应用谓词时,为了在特定索引处找到一个值,您现在需要知道结果数组中该索引之前的所有值,因为对于任何位置,一个值可能在那里,也许没有。

vector package solves this issue elegantly with stream fusion, and repa-array,Repa 的下一个版本,目前还处于实验阶段,似乎正在尝试使用类似的方法,除了扩展到更高的维度(我可能是错的,没看过太多密切)。

所以,简而言之,没有办法使用 Repa 风格的功能融合进行过滤。或者:

  • 坚持selectP - 更快(可能),但内存效率较低(肯定),或者
  • vector 包中搭载到 ifilter 以进行连续 过滤