尝试为自定义树数据结构定义Eq时出现模糊定义错误

时间:2015-04-06 18:14:15

标签: haskell

我正在尝试为Huffman树数据结构实现EqOrd,但我得到了几个“模糊定义”和范围相关的错误。我一直关注https://www.haskell.org/tutorial/classes.html

上的树例子
import Data.List

data Tree a = Leaf a Int | Internal (Tree a) (Tree a) Int deriving (Eq, Ord)

instance (Eq a) => Eq (Tree a) where
(Leaf a ac) == (Leaf b bc) = (a == b) && (ac == bc)
(Internal (Tree a1) (Tree a2) ac) == (Internal (Tree b1) (Tree b2) bc) = 
                    (a1 == b1) && (a2 == b2) && (ac == bc)
_ == _ = False

instance Ord (Tree a) where
Tree a <= Tree b = (freq a) <= (freq b)

freq :: Tree a -> Int
freq (Leaf _ c) = c
freq (Internal _ _ c) = c

我不确定什么是含糊不清的。它说==可能来自Prelude或我的代码。但是,我的==仅针对我的Tree定义,因此我不确定发生了什么。请帮助我理解并纠正这个问题。

1 个答案:

答案 0 :(得分:4)

问题是缩进。您需要使用==<=缩进所有行。编译器将instance (Eq a) => Eq (Tree a) where视为一个块,然后将树上==的定义视为完全独立的代码块。缩进这个和你的Tree a <= Tree b = ...行,它应该是好的。否则,您似乎在源代码的顶层定义了==,Haskell很乐意让您这样做。

由于您已经为Eq派生OrdTree,因此您不必自己定义它们。如果您想要自定义实例,那么不要派生它们。除此之外,您需要将Ord实例的定义修改为

instance Ord (Tree a) where
    a <= b = freq a <= freq b

freq的定义相同。您不需要在此处进行模式匹配,尤其是因为Tree是类型构造函数,但您只能与数据构造函数进行模式匹配。 LeafInternal是数据构造函数,因此可以进行模式匹配。您还需要为Eq实例修复此问题,但解决方案类似。