繁体   English   中英

Haskell(GHC)专业之旅和高效的TypeFamilies

[英]Haskell(GHC) specialization tour & efficient TypeFamilies

Haskell完全是关于抽象的。 但是由于所有抽象(多态)数据的通用表示(堆上的指针),抽象使我们付出了额外的CPU周期和额外的内存使用。 有一些方法可以使抽象代码在高性能要求下更好地发挥作用。 据我了解,一种完成方法是专业化-基本上是额外的代码生成(手动或通过编译器),对吗?

假设下面的所有代码都是严格的 (这有助于编译器执行更多优化?)

如果我们有一个函数sum

sum :: (Num a) => a -> a -> a

我们可以使用specialize pragma生成它的专门版本:

{-#SPECIALIZE sum :: Float -> Float -> Float#-}

现在,如果haskell编译器可以确定在编译时我们在两个Float上调用sum ,它将使用它的专用版本。 没有堆分配,对吗?

功能-完成。 相同的编译指示可以应用于类实例。 逻辑在这里不会改变,对吗?

但是数据类型呢? 我怀疑TypeFamilies在这里负责吗?

让我们尝试专门化依赖长度索引的列表。

--UVec for unboxed vector
class UVec a where
   data Vec (n :: Nat) a :: *

instance UVec Float where
   data Vec n Float where
     VNilFloat :: Vec 0 Float
     VConsFloat :: {-#UNPACK#-}Float ->
                   Vec n Float -> 
                   Vec (N :+ 1) Float

但是Vec有一个问题。 我们无法在其构造函数上进行模式匹配,因为每个UVec实例不必为Vec提供相同的构造函数。 这迫使我们为Vec的每个实例在Vec上实现每个函数(由于缺少模式匹配,这意味着它不能在Vec上实现多态)。 在这种情况下,最佳做法是什么?

正如您所说,我们无法在UVec a进行模式匹配,而无需知道a是什么。 一种选择是使用另一种类型类,该类通过自定义函数扩展向量类。

class UVec a => UVecSum a where
   sum :: UVec a -> a

instance UVecSum Float where
   sum = ... -- use pattern match here

如果稍后使用sum v其中v :: UVec Float ,则将调用实例中定义的特定于Float代码。

部分回答,但也许有帮助。

据我了解,一种完成方法是专业化-基本上是额外的代码生成(手动或通过编译器),对吗?

是的,这类似于C ++模板中的代码实例化。

现在,如果haskell编译器可以确定在编译时我们在两个Float上调用sum,它将使用它的专用版本。 没有堆分配,对吗?

是的,编译器会在可能的情况下调用专用版本。 不确定您对堆分配的含义。

关于向量的从属类型:通常(我从Idris知道),向量的长度在可能的情况下由编译器消除。 它用于更强大的类型检查。 在运行时,长度信息是无用的,可以丢弃。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM