2012-08-03 56 views
6

我正在瀏覽Data.Has的源代碼並試圖弄清楚它是如何工作的。我相信下面的代碼旨在允許某人將兩個值「加入」,例如a :: Ab :: B成爲具有ab的功能的新值。在類和實例聲明中鍵入關鍵字

我特別不明白type是指什麼類和實例聲明。

另外我不知道~符號的含義如下。

有人能解釋下面的代碼從Data.Has.TypeList的作品嗎?

-- | Provides type-list functionality 

module Data.Has.TypeList where 

import Control.Applicative 
import Data.Monoid (Monoid (..)) 
import Test.QuickCheck (Arbitrary (..), CoArbitrary (..)) 
import Data.Typeable 
import Data.Data 
-- | Cons a type onto type-list. 
data a ::: b = a ::: b deriving (Show,Eq,Ord,Read,Bounded,Typeable,Data) 

-- | The empty type-list. 
data TyNil = TyNil deriving (Read,Typeable,Data) 

-- | Appends a type-list and another. 
class Append a b where 
    type a :++: b 
    (.++.) :: a -> b -> a :++: b 
infixr 5 :++: 

-- Implementation of Append 

instance Append TyNil b where 
    type TyNil :++: b = b 
    _ .++. b = b 

instance (Append y b) => Append (x ::: y) b where 
    type (x ::: y) :++: b = x ::: (y :++: b) 
    ~(x ::: y) .++. b = x ::: (y .++. b) 
+0

它們被稱爲關聯類型同義詞。這些結構類似於函數依賴關係,但使用類型函數而不是關係。 – 2012-08-03 06:04:23

回答

7

type內部類型類和實例聲明的語法是TypeFamilies延伸的一部分。類型族可以被認爲是從類型到類型的函數。 Haskell wiki中有關於類型和數據族的詳細解釋(請參閱鏈接)。

應用於類型類型,類型族變爲關聯類型。在這方面,他們非常接近FunctionalDependencies,也就是說,他們允許非正式的實例解析。這需要充分解釋in the GHC manual

您示例中的類型定義非常簡單。 :::是2元組(一對值)的另一個名稱,並且TyNil與單元類型()同構。

我會嘗試讀取類和實例聲明,以便清楚它們的含義。

class Append a b where 
    type a :++: b 
    (.++.) :: a -> b -> a :++: b 
infixr 5 :++: 

申報多參數類型類Append a b與相關聯的類型a :++: b和一個方法功能(.++.)這需要的類型ab值併產生a :++: b類型的值。我們還設置(.++.)爲右結合優先5.

instance Append TyNil b where 
    type TyNil :++: b = b 
    _ .++. b = b 

聲明的Append a b的實例與固定的第一參數(TyNil)和任意第二參數(b),其中相關聯的類型a :++: b(在這種情況下它是TyNil :++: b)宣佈等於b。 (我不會描述什麼方法,這很清楚)。

instance (Append y b) => Append (x ::: y) b where 
    type (x ::: y) :++: b = x ::: (y :++: b) 
    ~(x ::: y) .++. b = x ::: (y .++. b) 

在形式x ::: y與第一參數聲明的Append a b一個實例在給定,已經有聲明的Append y b實例任意xy和任意第二參數b。相關類型a :++: b(這裏顯然爲(x ::: y) :++: b)被聲明爲等於x ::: (y :++: b)。方法定義在這裏也很清楚:它採用一對值和另一個值,並構造另一對,其中第一個元素與第一個參數相同,第二個元素是第一個參數的第二個元素,與第二個參數組合爲第二個參數,方法爲.++.。我們被允許使用,因爲.++.Append y b約束

這些(.++.)方法類的聲明和實例聲明的類型簽名:

(.++.) ::    a  -> b -> a :++: b 
(.++.) ::    TyNil -> b -> b 
(.++.) :: Append y b => x ::: y -> b -> x ::: (y :++: b) 

注意,在每個實例很抽象a :++: b轉變爲更具體的類型。在第一種情況下,它是普通的b,更復雜的是x ::: (y :++: b),其本身按:++:編寫。需要

相關聯的類型的這種聲明告訴型系統存在(在這種情況下a :++: b)某種類型的其是由單獨ab唯一確定。也就是說,如果typechecker知道,在某些表達ab類型相同,比方說,IntDouble和:

  1. 有一個約束Append a b;
  2. 有一種類型的類實例Append Int Double與聲明,比如說相關的類型,如type Int :++: Double = String

那麼typechecker就會知道,如果他滿足型a :++: b會知道,其實這類型String

至於~,它被稱爲'懶惰模式匹配'。這是非常清楚地解釋here

隨意問問是否仍有不清楚的地方。