为什么使Vector成为Functor、Monad、Applicative、Alternative、Foldable和Traversable实例的函数会变慢?

17

版本0.8的vector的更新日志中列出了以下变更并附带警告:

为boxed向量提供Functor、Monad、Applicative、Alternative、Foldable和Traversable实例(警告:它们往往较慢,只是为了完整性而提供)

有人能解释一下这是为什么吗?这只是类型类特化的正常代价,还是有更有趣的原因?

更新:查看某些特定实例,可以看到例如:

instance Foldable.Foldable Vector where
  {-# INLINE foldr #-}
  foldr = foldr

同样地,对于其他折叠操作也是如此。这是否意味着在一般情况下对于Vector折叠操作很慢?如果不是,那么是什么使得非特化的折叠操作变得足够慢以至于需要发出警告?

2个回答

15

我一年半前向Roman提交了这些实例的原始版本,并从那时起一直保持着向量实例。 (一旦它们迁移到向量中,我必须将这些实例从向量实例中删除,现在仅为真正奇特的东西维护它)。他的担忧是,如果人们使用这些实例进行多态操作,则使向量融合的规则无法触发,除非多态函数被内联化和单态化。

它们存在的原因是因为地球上并不是每一行代码都是针对向量的,即使是这样,有时候使用通用名称也很好。

慢是相对的。最坏的情况是它们表现得像其他任何人的fold、bind等,但Roman认为每一个装箱值都是个人侮辱。:)


8
我刚刚快速查看了源代码,实现看起来并不过于缓慢。我认为作者加入这个警告是因为当你使用Vector单子编写程序时,你从高层次的角度出发,很容易忘记每个>>=实际上是一个concatMap,而concatMap往往本质上较慢。
另一件事情是,对于非盒装类型,Vector特别快。因此,用户可能会被吸引使用单子符号(出于方便),而实际上应该使用非盒装类型(出于速度)。

1
这是一个有趣的观点。不过我会再等一会儿再接受答案,以防出现更少推测性的答案。(哦,我并不是在说什么消极的话...我想这个问题本身就有些推测性了——“当vector的作者们写下警告时,他们到底是什么意思?”) - gspr
没问题,我在这种情况下也会这样做——我的答案只是一个有根据的猜测。 - jaspervdj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接