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