如何创建包含预定义类型的Haskell类实例?

时间:2013-04-07 15:50:16

标签: class haskell types

我正在尝试创建一个包含预定义类型的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))

1 个答案:

答案 0 :(得分:4)

newtype使用AdjListGraph代替type同义词。你可以使用它所要求的TypeSynonymInstances扩展名,但是这会导致类型推断出现问题,因为类型同义词不会引发"#34;坚持"当它们扩展时,它们不一定具有选择正确类型类实例所需的正确形式。使用newtype将帮助您避免很多麻烦,即使它确实需要包装和展开。

原因是ghc通过匹配某事物的主要类型来解析哪个类型类实例。您的AdjacencyListGraph主体类型实际上是[(a, [a])],而type同义词只是为其创建别名,但不会更改其主体类型。 newtype实际上更改了主体类型,这就是它与类型类很好地结合的原因。但是,它要求您专门包装和解包值,以便ghc始终知道要匹配的主要类型。