【问题标题】:How do I create a Haskell class instance including a predefined type?如何创建包含预定义类型的 Haskell 类实例?
【发布时间】:2013-03-29 15:55:06
【问题描述】:

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

【问题讨论】:

  • 嗯...您尝试过 GHC 建议的修复方法吗?附带说明一下,您为什么在实例声明的开头要求 Graph a?
  • 这个错误正是错误信息所说的。
  • (makePairs (fst (head a)) (snd (head a))) 也是错误的。 a的类型为AdjListGraph a,即[(a, [a])]。它与makePairs :: Node -> [Node] -> [(Node, Node)] 相矛盾。如果您将makePairs 设为通用,例如删除其类型注释,(makePairs (fst (head a)) (snd (head a))) ++ (arcs (tail a)) 将与 arcs :: g -> [Arc] 矛盾

标签: class haskell types


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2016-12-05
    • 1970-01-01
    • 2017-04-03
    • 2015-02-03
    • 1970-01-01
    • 2013-11-25
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多