【问题标题】:How to Pattern Match an Empty Vector in Haskell?如何在 Haskell 中对空向量进行模式匹配?
【发布时间】:2016-04-14 15:15:36
【问题描述】:

假设我想使用模式匹配实现列表的长度函数,那么我可以这样做:

length' :: (Num b) => [a] -> b  
length' [] = 0  
length' (_:xs) = 1 + length' xs  

我可以用Vectors 做类似的事情吗?

【问题讨论】:

  • 您可以使用ViewPatternsPatternSynonyms 之类的东西对抽象类型的东西进行模式匹配,但是如果您想在Vector 上编写类似length 的归纳函数,为什么不只是使用foldlfoldr,或vector 提供的其他十几个“折叠”变体中的任何一个?如果您使用例如,这具有推广到每个 Foldable 的优势。 Data.Foldable.foldr 而不是 vector 中的特定版本。
  • 也许case splitAt 1 v of ... ?如上所述,可能制作成ViewPattern
  • 注意模式同义词;如果设计不当,它们可能会破坏性能直觉。
  • 经验法则:在模式同义词上应用或匹配应该分摊 O(1) 时间,即使该值被持久使用。我永远不会容忍比多对数时间更糟糕的模式同义词。

标签: haskell pattern-matching pattern-synonyms


【解决方案1】:

vector 库的各种 Vector 类型是不透明类型,它们不公开其数据构造函数,因此您无法对它们进行模式匹配。

有一些方法可以解决这个问题,例如 ViewPatterns(正如 user2407038 的评论所提到的),但您肯定 想将这些与向量一起使用,因为您可能会 抛弃使用向量的优势

vector 库的亮点在于它基于两个概念实现:

  1. 向量被具体化为固定大小的连续内存数组,它提供比单链表或树更好的内存局部性;
  2. 大量向量操作是根据可熔流实现的,其操作编译为不为中间向量分配内存的循环。

(1) 表示向量不像列表那样具有自然的“头”和“尾”——列表字面意思是一对头和尾。如果您要使用某种视图模式在向量顶部施加头+尾结构,您将有效地创建向量元素的单链表,这可能会触发每个节点的内存分配查看类型。

如果您使用ViewPatterns 将向量视为有效的单链表,为什么不直接将向量转换为列表?

无论如何,由于上面提到的设计要点,对于vector,您真的希望尽可能坚持使用the operations provided by the library itself,因为它们会利用库的性能特性。

我怀疑在许多情况下测试向量的大小可能不是一个最佳想法。例如,在这样的代码中:

example :: Vector something -> Vector somethingElse
example as 
  | Vector.null as = ...
  | otherwise      = ...

...我希望(但尚未验证!)这将强制向量 as 被物化,以便我们可以测试它是否为空,如果测试可以被消除或移动到其他地方“...”位中的操作可能会与使用example 的上下文融合。

【讨论】:

  • Vector.empty :: Vector a 实际上返回一个空向量。您可能想改用Vector.null :: Vector a -> Bool
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多