2012-03-15 66 views
4

例如使用一個類我有一個代碼以下方案:哈斯克爾:在另一個

class First s where 
    func1 :: s -> s 
class Second a where 
    func2 :: s -> a s 

data D s = D {value :: s} 
myFunc2 :: First s => s -> D s 
myFunc2 = undefined 

在共同FUNC2的說法不能成爲第一的實例。只有當它是First的值實例時,我纔想讓D的第二個實例。 後來我想這種情況下:

instance Second D where 
    func2 = myFunc2 

但我得到一個錯誤:

No instance for (First s) 
    arising from a use of `myFunc2' 

好吧,讓我們的實例是:

instance First s => Second D where 
    func2 = myFunc2 

但是這給了錯誤:

Ambiguous constraint `First s' 
    At least one of the forall'd type variables mentioned by the constraint 
    must be reachable from the type after the '=>' 
In the instance declaration for `Second D' 

所以,是有一種方法可以從其他類的某些條件中獲得類的實例,但在'=>'之後沒有所有類型變量?

回答

7

,我認爲它有助於思考什麼是

class Second a where 
    func2 :: s -> a s 

一個Second實例承諾,func2任何類型s定義定性的意思。但是myFunc2並非如此,因爲myFunc2僅針對那些存在First實例的s而定義。這意味着,因爲您已經定義了FirstSecond,所以不可能在Second實例中使用myFunc2(除非存在一個全面的forall s . First s實例,但我假設不是,或者您不打算製作一個類型類)。因此,你將不得不改變至少一件事。 Grzegorz建議您可以重新定義Second。如果你不喜歡,你可以重新定義Second

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances #-} 

class Second a s where 
    func2 :: s -> a s 

instance First s => Second D s where 
    func2 = myFunc2 

注意,這是說的東西比你原來寫什麼不同,因爲現在一個Second實例並不保證func2是多態的。但是,我認爲這更接近於當您說「僅在第一個值的實例中才創建D的第二個實例」時所表達的意思。也許它會在你的代碼中被接受。

+0

謝謝,這看起來像我能做的最好的事情。 – spontaliku 2012-03-15 12:54:40

6

確切的解決方案將取決於什麼代碼試圖做的,但問題是,你給func2類型簽名不提First s約束,而你對Second D實例func2定義需要它。以下編譯:

class First s where 
    func1 :: s -> s 
class Second a where 
    func2 :: First s => s -> a s 

data D s = D {value :: s} 
myFunc2 :: First s => s -> D s 
myFunc2 = undefined 

instance Second D where 
    func2 = myFunc2 
+0

問題是func2的參數不能是第一個共同的實例。只有當它是First的值實例時,我纔想讓D的第二個實例。我糾正了問題。 – spontaliku 2012-03-15 07:59:46