2013-11-22 40 views
1

我在幾個不同的地方碰到了Haskell中名爲TypeCast的類型類。Haskell TypeCast類型

這是相當神祕的,我似乎無法完全解析它。

class TypeCast a b | a -> b, b -> a  where typeCast :: a -> b 
class TypeCast' t a b | t a -> b, t b -> a where typeCast' :: t -> a -> b 
class TypeCast'' t a b | t a -> b, t b -> a where typeCast'' :: t -> a -> b 

instance TypeCast'() a b => TypeCast a b where typeCast x = typeCast'() x 
instance TypeCast'' t a b => TypeCast' t a b where typeCast' = typeCast'' 
instance TypeCast''() a a where typeCast'' _ x = x 

http://okmij.org/ftp/Haskell/typecast.html給出了這個代碼有益的,但敷衍評論。欲瞭解更多信息,該頁面指向http://homepages.cwi.nl/~ralf/HList/paper.pdf這是一個斷開的鏈接。

我看到TypeCast是一類允許您從一種類型投射到另一種類型,但我不明白爲什麼我們需要TypeCast'TypeCast''

它看起來像所有這些代碼所做的是允許您將自己的類型。在我看到的一些示例代碼中,我嘗試用它替換它:

class TypeCast a b | a -> b, b -> a where typeCast :: a -> b 
instance TypeCast a a where typeCast a = a 

並且樣本仍然工作。我一直在看的樣本大多來自第一個鏈接。

我想知道是否有人可以解釋這六條線是什麼。

+1

最近的HList使用'〜'而不是'TypeCast'。您可以從archive.org獲取該文件 – aavogt

回答

5

TypeCast的實際用途是什麼?

它不用於檢索關於存在類型的類型信息(這會破壞類型系統,所以它是不可能的)。要理解TypeCast,我們首先必須瞭解有關haskell類型系統的一些特定細節。請看下面的激勵例如:

data TTrue 
data TFalse 

class TypeEq a b c | a b -> c 

instance TypeEq x x TTrue 
instance TypeEq x y TFalse 

這裏的目標是有一個布爾標誌 - 在類型級別 - 它告訴你如果兩個類型相同。您可以使用~進行類型等同 - 但這隻會導致您在等效類型上失敗(即Int ~ Bool未編譯,而TypeEq Int Bool r將給出r ~ TFalse作爲推斷類型)。但是,這不會編譯 - 功能依賴衝突。原因很簡單 - x x只是x y(即x ~ y =>x y == x x)的實例,因此根據fundeps的規則(請參閱文檔以獲取規則的完整詳細信息),這兩個實例的值必須相同(c(或者這兩個值必須相互檢驗 - 它們不是)。

TypeEq類存在於HList庫 - 讓我們來看看它是如何實現的:

class HBool b => TypeEq x y b | x y -> b 
instance TypeEq x x HTrue 
instance (HBool b, TypeCast HFalse b) => TypeEq x y b 
-- instance TypeEq x y HFalse -- would violate functional dependency 

當然這些實例並不衝突 - HTrueb一個實例。可是等等! TypeCast HFalse b暗示b必須HFalse?是的,它的確如此,但編譯器在嘗試解決fundep衝突時未檢查類實例約束。這是允許這個類存在的關鍵「特徵」。作爲一個簡短的說明 - 這兩個實例仍然重疊。但是由於-XUndecidableInstances -XOverlappingInstances,編譯器會選擇第一個實例優先,由於第一個實例更「特定」(在這種情況下,這意味着它最多有2個唯一類型 - xHTrue,而另一個實例至多有3個)。您可以在文檔中找到UndecidableInstances使用的全套規則。

爲什麼TypeCast是這樣寫的?

如果你看看HList的源代碼,有多種實現TypeCast。一種實現方式是:

instance TypeCast x x 

人們會假設的直接實例將起作用。不!從該文件中包含上述定義的註釋:

A generic implementation of type cast. For this implementation to 
    work, we need to import it at a higher level in the module hierarchy 
    than all clients of the class. Otherwise, type simplification will 
    inline TypeCast x y, which implies compile-time unification of x and y. 

也就是說,類型簡化器(其工作是清除類型同義詞,不斷類限制使用)會看到x ~ yTypeCast x x因爲這是隻有匹配的實例,但只在某些情況下。由於在不同情況下行爲不同的代碼是「非常差」,因此HList的作者有第二個實現,即原始文章中的一個。讓我們一起來看看:(!該簡化器不會做)

class TypeCast  a b | a -> b, b -> a 
class TypeCast' t a b | t a -> b, t b -> a 
class TypeCast'' t a b | t a -> b, t b -> a 

instance TypeCast' () a b => TypeCast a b 
instance TypeCast'' t a b => TypeCast' t a b 
instance TypeCast''() a a 

在這種情況下,TypeCast x y可以從未被簡化不看類約束;沒有實例頭這可能暗示x ~ y

但是,我們仍然需要在某個時間段聲明x ~ y - 所以我們用更多的類來做到這一點! 我們知道a ~ bTypeCast a b的唯一方法是TypeCast() a b意味着a ~ b。如果TypeCast''() a b意味着a ~ b,則只有這種情況。

我不能給你整個故事unfortunatley;我不知道爲什麼

instance TypeCast'() a b => TypeCast a b 
instance TypeCast'() a a 

不足夠(它的作品 - 我不知道爲什麼它不會被使用)。我懷疑它與錯誤消息有關。我相信你可以追蹤奧列格並問他!

2

該HList文件發表在2004年Haskell研討會的會議記錄中,因此可以從ACM DL和其他檔案中獲得。唉,在發佈的版本中的解釋是縮寫爲缺乏空間。有關詳細解釋,請參閱作爲技術報告發布的論文的擴展版本,其版本號爲 http://okmij.org/ftp/Haskell/HList-ext.pdf(自從Ralf很久以前離開CWI後,CWI鏈接確實不再有效)。請參閱該TR中的附錄D TypeCast的解釋。

在最新的GHC中,代替TypeCast x y約束,您可以編寫x ~ y。沒有相應的typeCast方法:它不再是必需的。當你編寫約束時,GHC會自動和幕後合成類似於類似的東西(稱爲強制)。

直接在電子郵件中詢問我一個問題通常會得到更快的答覆。