【问题标题】:Haskell: Filtering based on an index vector, using only basic higher-order functionsHaskell:基于索引向量的过滤,仅使用基本的高阶函数
【发布时间】:2014-07-24 08:27:43
【问题描述】:

问题

我有一个大小为 N 的向量 a 保存样本数据,另一个向量 b 大小 M (N>M) 持有索引。我想获得一个大小为 N 的向量 c,其中包含来自 a 的过滤元素strong> 基于 b 中的索引。

问题

是否可以在不使用列表解析的情况下实现所需的功能,只使用基本的高阶函数,如 map、zipWith、filter 等(更准确地说,它们的等价物 mapV、zipWithV、filterV 等)

先决条件:

我正在使用 Haskell 嵌入式域特定语言(ForSyDe,模块ForSyDe.Shallow.Vector),仅限于一组硬件合成功能。为了尊重设计方法,我只能使用提供的函数(因此我不能使用列表推导等)

【问题讨论】:

  • 列表推导式可以相当简单地转换为mapfilterzipWith 等。事实上,列表推导式只是一元函数的语法糖,而您的Vector 类型可以成为一个单子,所以你可以只写列表理解版本并打开MonadComprehensions

标签: haskell filter higher-order-functions


【解决方案1】:

免责声明:

我没有测试此代码的功能,因为 cabal 开始四处窃听。它适用于列表,并且当我将每个向量转换为列表时,它应该可以正常工作,尽管可能会出现问题。


试试这个:

indexFilter :: (Num b, Eq b, Enum b) => Vector a -> Vector b -> Vector a
indexFilter vector indices = vector (map fst (filter (\x -> (snd x) `elem` (fromVector indices)) vectorMap))
 where
   vectorMap = zip (fromVector vector) [0..]

indexFilter 采用(<element>, <index>) 形式的元组列表,然后返回索引在向量 b 中的所有元素的向量。 vectorMap 只是 a 的元素及其在向量中的索引的压缩。

【讨论】:

  • 谢谢,我现在正在尝试您的方法,将其转化为我的问题(应用一些约束使其可合成)。另一方面,这似乎是一个很好的答案,并且非常有意义。
  • @GeorgeUngureanu 如果出现任何进一步的问题,请告诉我
  • 我已将此答案标记为正确答案,因为它确实回答了我的问题。不过,我没有解决我的问题,因为有几个没有提到的设计方法限制。此外,所提供的答案引发了引发下述解决方案的思路。
【解决方案2】:

虽然ThreeFx 提供的答案是对问题的正确答案,但由于设计方法 (ForSyDe) 强制执行的几个约​​束,它并没有解决我的问题,这些约束没有被提及:

  • 不能使用列表(它们不能合成到其他后端)。 ForSyDe 提供了两个数据容器:Signal(用于时间跨度)和 Vector(用于空间跨度)。这应确保系统综合的可分析性。
  • elem 没有 ForSyDe.Shallow.Vector 实现

解决方案 1

仅使用库提供的,我找到的最短解决方案是:

indexFilter1     :: (Num b, Eq b, Enum b) => Vector a 
                     -> Vector b 
                     -> Vector (Vector a)
indexFilter1 v = mapV (\idx -> selectV idx 1 1 v)

输出向量可以进一步展开,具体取决于进一步的使用。

解决方案 2

翻译ThreeFx的解决方案以满足上述约束:

 indexFilter       :: (Num b, Eq b, Enum b) => Vector a 
                      -> Vector b 
                      -> Vector a
 indexFilter v idx = mapV (fst) (filterV (\x -> elemV (snd x) idx) vectorMap)
     where
       vectorMap = zipWithV (\a b -> (b, a)) (iterateV size (+1) 0) v
       size      = lengthV v
       elemV a   = foldlV (\acc x -> if x == a then True else acc) False

【讨论】:

    猜你喜欢
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    相关资源
    最近更新 更多