簡體   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