2016-11-19 23 views
1

我想解決清潔這個問題(非常類似於Haskell這樣的語言):如何用兩個模板參數編寫一個類,其中一個是另一個的列表/數組?

有一個class Node t,有兩種情況:instance Node EdgeListinstance Node Adjacency。我想創建一個Graph,它是一個數組或節點列表。

Graph的定義是:

class Graph t1 t2 | Node t2 where 
    resetGraph :: (t1 t2) -> (t1 t2) 
    graphSize :: (t1 t2) -> Int 
    ... 

我還想寫的實例。一個有數組,另一個有列表。首先,我試圖與名單,但我得到一個錯誤:t2 not defined

instance Graph [t1] t2 | t2 t1 where 
    (resetGraph) :: [t1] -> [t1] 
    (resetGraph) x = [] 
    ... 

它將被稱爲例如像這樣:resetGraph listAdj其中listAdj是Adjacency節點

的列表。如果我只是寫:instance Graph [tt] tt然後我得到這個錯誤:Error: this type variable occurs more than once in an instance type

回答

1

首先要理解此處是當你寫

class Graph l t | Node t where 
    resetGraph :: (l t) -> l t 

你給l*->*。種類是類型的抽象。粗略地說,親切的*意味着你有一個'完整的'類型。例如,Int,[Char],a -> String都是*。當一個類型仍然'需要一個參數'時,它有種類*->*。舉例來說,如果你有:: Maybe a = Just a | Nothing,然後Maybe Int是樣*,而僅僅是Maybe*->*因爲它仍然需要一個參數。所以,寫resetGraph :: (l t) -> l t時,編譯器識別t是一個參數l,所以唯一的辦法給予resetGraph*(這是必要的功能),是給l*->*(和t*)。

你需要知道的第二件事是,類型,[Char](Int,Int)a -> Real根都被寫入前綴,以及:[] Char(,) Int Int(->) a Real。你可以比較[]Maybe:它仍然需要一個參數(這裏是Char)是一個完整的類型。因此,類型[]有種類*->*。同樣,(,)也有*->*->*,因爲它仍然需要兩種類型才能完成,如(->)。 (注意:這在language report的第4.5節中有記錄)。

結合這兩個,你應該寫:

instance Graph [] Adjacency where 
    ... 

然後,resetGraph類型決心([] Adjacency) -> [] Adjacency這是一樣的[Adjacency] -> [Adjacency]

對於數組,該前綴表示法是{} Adjacency{Adjacency}

順便說一句:類似這樣的事情在做StdEnv與類length

// StdOverloaded.dcl 
class length m :: !(m a) -> Int 

// StdList.icl 
instance length [] where ... 
+0

謝謝你,我現在好理解。出於某種原因,我在'instance Graph [] Node ...'處得到一個錯誤。錯誤是:'節點未定義'。節點由兩個實例定義。我在'class Graph t2 t2 |沒有錯誤節點t2在哪裏' –

+0

@IterAtor不客氣。對不起,我寫了'Node',我應該寫'Adjacency'或'EdgeList'。 (錯誤告訴你'Node'不是一個類型。)現在已經修復了。 – Keelan

+0

但我覺得我不應該使用'Adjacency'或'EdgeList'直接,因爲每次我都需要在'Graph'功能'Node'定義(該功能在這兩種情況下的定義) –

相關問題