1

定義済みの型を含む Haskell クラスのインスタンスを作成しようとしていますが、「Graph (AdjListGraph a)' (All instance types must be of the form (T t1 ... tn) where T is not a synonym. Use -XTypeSynonymInstances if you want to disable this.) In the instance declaration forグラフのインスタンス宣言が不正です (AdjListGraph a)」というエラーが表示され続けます。

誰かがこの問題を手伝ってくれますか? コードは次のとおりです。

type Node = Int

type Arc = (Node, Node) 

containsArc :: Node -> Node -> [Arc] ->Bool
containsArc a b [] = False
containsArc a b (x:xs)
    | (fst x == a && snd x == b) = True
    | otherwise = containsArc a b xs

fstNode :: [Arc] -> Node -> [Node]
fstNode arcs n
    | (n == (fst (head arcs))) = (snd (head arcs)) : (fstNode (tail arcs) n)
    | otherwise = fstNode (tail arcs) n

sndNode :: [Arc] -> Node -> [Node]
sndNode arcs n
    | (n == (snd(head arcs))) = (fst (head arcs)) : (sndNode (tail arcs) n)
    | otherwise = sndNode (tail arcs) n 

class Graph g where

    build :: [Node] -> [Arc] -> g

    nodes :: g -> [Node] -- lista nodurilor din graf

    arcs :: g -> [Arc] -- lista muchiilor din graf

    nodeOut :: g -> Node -> [Node]

    nodeIn :: g -> Node -> [Node]

    arcExists :: g -> Node -> Node -> Bool

    arcExists g a b
        | (arcs g) == [] = False
        | otherwise = if (fst (head (arcs g)) == a && snd (head (arcs g)) == b) then True else containsArc a b (tail (arcs g))

    nodeIn g n = sndNode (arcs g) n
    nodeOut g n = fstNode (arcs g) n


type AdjListGraph a = [(a, [a])]

makePairs :: Node -> [Node] -> [(Node, Node)]
makePairs a [] = []
makePairs a (x:xs) = (a, x) : makePairs a xs

instance Graph a => Graph (AdjListGraph a) --this is where i get the error-- where
    arcs a 
        | a == [] = []
        | otherwise = (makePairs (fst (head a)) (snd (head a))) ++ (arcs (tail a))

    nodes a
        | a == [] = []
        | otherwise = (fst (head a)) : (nodes (tail a))
4

1 に答える 1

4

同義語の代わりにnewtypeforを使用します。要求どおりに拡張機能を使用できますが、型の推論に問題が発生します。これは、型シノニムが「固執」せず、展開されたときに、正しい型クラス インスタンスを選択するために必要な正しい形式を必ずしも持っていないためです。を使用すると、ラッピングとアンラッピングが必要になる場合でも、今後の多くの頭痛の種を回避するのに役立ちます。AdjListGraphtypeTypeSynonymInstancesnewtype

その理由はghc、何かのプリンシパル型を照合することによって、どの型クラス インスタンスを解決するかです。あなたAdjacencyListGraphのプリンシパル型は実際には[(a, [a])]であり、typeシノニムはそのエイリアスを作成するだけで、そのプリンシパル型を変更しません。Anewtypeは実際にプリンシパル型を変更するため、型クラスでうまく機能します。ghcただし、常にどのプリンシパル タイプに一致するかを常に認識できるように、値を具体的にラップおよびアンラップする必要があります。

于 2013-04-07T16:46:05.483 に答える