[英]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.