所以有时我需要编写一个我在Hackage上找不到的数据结构,或者我发现的数据结构没有经过测试或质量不足以让我信任,或者它只是我不想成为依赖项的东西。我现在正在阅读Okasaki的书,它非常擅长解释如何设计渐近快速的数据结构。
但是,我正在专门研究GHC。常数因素对我的应用来说是一个大问题。内存使用对我来说也是一个大问题。所以我对GHC有特别的疑问。
特别是
我浏览了网络上的各个地方,我对如何使用GHC有一个含糊的想法,例如,使用UNPACK
pragma查看核心输出,等等。但我不确定我明白了。
所以我弹出了我最喜欢的数据结构库,容器,并查看了Data.Sequence模块。我不能说我理解他们正在做的很多事情,以使Seq快速。
引起我注意的第一件事是FingerTree a
的定义。我认为这只是我对手指树不熟悉。引起我注意的第二件事是所有SPECIALIZE
pragma。我不知道这里发生了什么,我很好奇,因为这些都遍布整个代码。
许多函数也有一个INLINE
pragma与它们相关联。我可以猜到这意味着什么,但我如何判断何时INLINE
函数?
applicativeTree
的函数,它显然专门用于Identity monad,这增加了输出的共享功能。我不知道这里发生了什么。什么巫术被用来增加分享?
无论如何,我不确定从Data.Sequence中学到很多东西。是否有其他“模范程序”我可以阅读以获得智慧?我真的很想知道当我真正需要它们更快时,如何更新我的数据结构。有一件事特别是编写使融合变得容易的数据结构,以及如何编写好的融合规则。
答案 0 :(得分:41)
这是一个很大的话题!大多数已在其他地方解释过,所以我不打算在这里写一本书章。代替:
Johan Tibell在这个主题上写了很多:
从这里开始的一些事情:
还有其他一些事情:
答案 1 :(得分:13)
applicativeTree
非常花哨,但主要是以与FingerTrees有关的方式,这本身就是一个非常奇特的数据结构。我们讨论了错综复杂的问题over at cstheory。请注意,applicativeTree
编写为适用于任何 Applicative。它恰好发生在它专用于Id
时,它可以以其它方式共享节点。您可以通过内联Id
方法并查看发生的情况来自行完成专业化。请注意,此专门化仅在一个位置使用 - O(log n)replicate
函数。事实上,更通用的功能专门针对常量情况,这是一个非常聪明的代码重用,但实际上就是这一切。
总的来说,我认为Sequence
教授更多关于设计持久数据结构的知识,而不是关于实现性能的所有技巧。 Dons的建议当然很棒。我还要浏览真正的规范和调优库的来源 - Map
,IntMap
,Set
和IntSet
in特定。与此同时,值得一看米兰的paper on his improvements to containers。