2012-11-24 127 views
2

我有一個非常簡單的代碼如下:覆蓋率條件失敗

{-# LANGUAGE 
    MultiParamTypeClasses, 
    FunctionalDependencies, 
    FlexibleInstances, 
    FlexibleContexts 
#-} 

class Graph g n e | g -> n e where 
    nodes   :: g -> [n]        
    edge   :: g -> (n,n) -> Maybe e     

instance Graph g Int e where 
    nodes g = [] 
    edge g (n1,n2) = Nothing 

我得到了相關的覆蓋條件的誤差爲函數依賴的一個失敗。我需要添加-XUndecidableInstances來允許這個嗎?或者我如何解決這個問題?謝謝

+5

你的函數依賴性表明,你選擇'g'類型的選擇分別決定你的節點和元素類型'n'和'e'。那麼,說所有圖形類型'g'(不知道關於'g')是否確定節點類型是'Int'? – sabauma

+0

@sabauma,謝謝!我從來不知道覆蓋情況如何,但這個小例子顯示了我! :-) – luqui

+0

@luqui嘿,我從來沒有聽說過「覆蓋條件」之前。我只是推理代碼。 – sabauma

回答

1

您的函數依賴性表示您選擇的類型g分別決定您的節點和元素類型n和e。那麼,說所有圖形類型g(不知道g)是否確定節點類型爲Int?

5

您的情況中的問題不是Int而是e。覆蓋條件記錄在GHC's manual Sect。 7.6.3.2。輕鬆規則的實例背景並說:

覆蓋條件。對於每個函數依賴,電視 - >電視權利,類,每一種類型的變量S(電視)必須出現在S(電視),其中S是取代映射每種類型將類聲明中的變量轉換爲實例聲明中的相應類型。

這是什麼意思在實踐中?在你的情況下,你的函數依賴表示g -> n e,這意味着對於每種情況,由ne表示的類型對於由g表示的類型是唯一的。現在讓我們假設你正在定義一個實例

instance Graph SomeTypeG SomeTypeN SomeTypeE where 
    ... 

覆蓋率條件說,出現在SomeTypeESomeTypeN任何類型的變量必須出現在SomeTypeG。如果不滿意會發生什麼?假設類型變量a出現在SomeTypeE中,但不在SomeTypeG中。然後,對於固定的SomeTypeG,我們可以通過用不同的類型代替a來實現無數個可能的實例。

在你的情況

instance Graph g Int e where 
    ... 

e就是這樣一個類型的變量,因此受到覆蓋條件它必須出現在g,這是不正確的。因爲它沒有出現在那裏,所以你的定義暗示Graph g Int Int是一個實例,Graph g Int (Maybe Char)是另一個實例等,與功能依賴關係相矛盾,要求只有一個實例。

如果您已經定義類似

instance Graph g Int Char where 

那將是美好的,因爲有在IntChar沒有類型的變量。另一個有效的實例可能是

instance Graph (g2 e) Int e where 

其中g2現在是一種* -> *。在這種情況下,e出現在g2 e中,它滿足覆蓋條件,實際上,e始終由g2 e唯一確定。