我会用一个更具体的问题来激发一般性问题:
在GHC Haskell中,Cofree [] a
应该与containers
- 样式Data.Tree a
具有相同的效果吗?或者额外的多态性会导致某种运行时成本吗?
一般来说,增加一种类型的“arity”会增加额外的运行时成本吗?
答案 0 :(得分:1)
我认为一个更经典的具体例子可能是矢量或数组。 vector package导出“盒装”和“未装箱”的矢量。虽然盒装向量可以包含任何Haskell类型(包括函数),但未装箱的向量要求其元素是Unbox
类型类的实例。虽然这意味着没有指针间接的更高效的压缩内存表示,但是你不能再为未装箱的向量定义Functor
实例,因此它会失去一般性。
如果您使用
fmap :: (a -> b) -> Vector a -> Vector b
在类型
的函数中f :: Functor f => f SomeType -> f SomeOtherType
“字典”,即具有相应fmap
实现的记录将在运行时作为附加隐式参数传递。您可以通过使用-ddump-simpl
标志查看GHC生成的“Core”输出来实际看到这一点。具体来说,上面f
的arity将是两个而不是一个。
在某些情况下,GHC可以通过创建功能的专用版本来优化此开销。您可以通过使用SPECIALIZE/INLINABLE/... pragma,使用显式导出列表,可能添加一些严格性以及一些其他调整来提供帮助,这些调整也会被描述为in the documentation。
关于使用参数化多态类型的开销,它当然取决于。我个人最坏的情况是内部数字循环中的因子100(通过添加一个SPECIALIZE编译指示来解决),所以它可以确实咬你。幸运的是,使用分析工具并记住字典对函数的影响,跟踪这些问题变得非常系统化。