我提出这个问题是参考这个SO问题。Don Stewart的答案说:"第一行表示"你的代码高度多态性,将所有float变量更改为Double...",这样可以使代码性能提高4倍。
我有兴趣在Haskell中执行矩阵计算,是否应该养成编写高度单态化代码的习惯?
但是一些语言利用特设多态性生成快速代码,为什么GHC不会或无法实现?(请阅读C ++或D)
为什么我们不能像blitz++或eigen一样拥有Haskell?我不明白GHC中的类型类和(特设)多态性的工作原理。
我提出这个问题是参考这个SO问题。Don Stewart的答案说:"第一行表示"你的代码高度多态性,将所有float变量更改为Double...",这样可以使代码性能提高4倍。
我有兴趣在Haskell中执行矩阵计算,是否应该养成编写高度单态化代码的习惯?
但是一些语言利用特设多态性生成快速代码,为什么GHC不会或无法实现?(请阅读C ++或D)
为什么我们不能像blitz++或eigen一样拥有Haskell?我不明白GHC中的类型类和(特设)多态性的工作原理。
INLINABLE
而不是SPECIALIZE
。在函数上使用INLINABLE
注释可确保模块导出函数的原始源代码,以便可以在使用点进行特化。这通常消除了为每个用例提供单独的SPECIALIZE
指示符的需要。INLINE
不同,INLINABLE
不会改变GHC的优化启发式方法。它只是表示“请导出源代码”。我不明白在GHC中类型类是如何工作的。
好的,请考虑这个函数:
linear :: Num x => x -> x -> x -> x
linear a b x = a*x + b
这个函数需要三个数字作为输入,并返回一个数字作为输出。该函数接受任何数值类型;它是多态的。 GHC 是如何实现这个功能的呢? 好吧,本质上编译器创建了一个“类字典”,其中包含所有类方法(在这种情况下是+
、-
、*
等)。 这个字典成为函数的一个额外隐藏参数。类似于这样:
data NumDict x =
NumDict
{
method_add :: x -> x -> x,
method_subtract :: x -> x -> x,
method_multiply :: x -> x -> x,
...
}
linear :: NumDict x -> x -> x -> x -> x
linear dict a b x = a `method_multiply dict` x `method_add dict` b
每次调用函数时,编译器会自动插入正确的字典,除非调用函数也是多态的,这样它本身就已经收到了一个字典,所以只需将其传递即可。linear
这样的小函数,每次调用时都很可能被内联,从而不会产生多态开销和少量代码重复 - 就像 C++ 模板一样。对于更大、更复杂的多态函数,可能会有一些成本。通常情况下,编译器决定这个问题,而不是你 - 除非你想开始在各个地方撒上 pragma。;-) 或者,如果您实际上没有使用任何多态性,可以只给所有东西提供单态类型签名... - MathematicalOrchid