2013-03-05 102 views
6

我有一個叫Foo的類,它擁有一個函數gen :: Int -> [Foo]。舉例來說,我可以做一個實例的Foo這樣:讓一個類成爲另一個類的實例

data FooTest = FooTest Int 

instance Foo FooTest where 
    gen n = replicate n (FooTest 0) 

現在,讓我們想象我有一個名爲Bar定義一個函數bar :: Bar -> IO()另一個類。 Foo的每個實例都必須是Bar,的一個實例,但Bar實現對於每個實例都非常相似。這裏有一個例子:

class Foo f where 
    gen :: Int -> [f] 

class Bar b where 
    bar :: b -> IO() 

instance Bar Foo where -- obviously that doesn’t work 
    bar _ = putStrLn "bar through any Foo instance" 

instance (Foo f) => Bar f where -- this needs the FlexibleInstance GHC extension first, then it still throws shit saying that the constraint is not smaller that I don’t shit 
    bar _ = putStrLn "bar through any Foo instance" 

這裏的問題是,我找不到任何方法可以讓另一個類的一個實例來提的是,第一類的任何實例將共享相同的實施實例化其他類。

有什麼想法?

在此先感謝。

回答

4

可以做到正是你想用你的最後一個實例與擴展什麼:FlexibleInstancesUndecidableInstances

就像名稱所暗示的那樣,第二個擴展允許您編寫不會終止的實例。這可能導致編譯時無限循環;然而,這個實現在某個遞歸深度被任意限制,所以你不應該有實際無限的編譯時間。

我不知道有什麼辦法做到這一點,沒有任何擴展。但是,使用擴展並不是天生就不好,除非您將來可能要使用其他編譯器。

此外,隨機樣式注:如果您只有一個約束,括號是可選的。所以你可以這樣寫:

instance Foo f => Bar f where ... 

這不是很重要,但我認爲第二個版本看起來更好。

+0

非常感謝!就我所知,「FlexibleInstance」是什麼?這兩個擴展是成對使用的嗎? – phaazon 2013-03-05 09:46:18

+1

我始終圍繞所有上下文編寫括號。這使得類型簽名和類/實例頭更具可讀性。所以我不同意你的風格。 – ertes 2013-03-05 10:05:31

+0

關於FlexibleInstaces:另請參閱本QA:http://stackoverflow.com/questions/8367423/are-haskell-flexibleinstances-a-stable-extension-to-the-language – scravy 2013-03-05 10:27:20

相關問題