Haskell中Eq实例创建与计算报错问题求助
解决Haskell自定义Eq与Rechner类的编译错误
错误原因分析
- 缺少Rechner约束:在自定义
Eq (Ausdruck a)实例的Add1分支中调用了rechnen函数,但实例声明的上下文仅包含Prelude.Eq a,编译器无法自动推导出Rechner (Ausdruck a)约束,导致无法调用rechnen。 - 缺少Double的自定义Eq实例:
rechnen返回Double类型,你使用自定义的Aufgabe.==比较该类型值,但未给Double实现Aufgabe.Eq实例,编译器找不到对应逻辑。 - isEqual函数约束错误:函数依赖自定义
Eq实现,但原类型签名使用了Prelude.Eq约束,与实际需求不符。
修正后的代码
data Ausdruck a = Zahl1 a | Add1 (Ausdruck a) (Ausdruck a) class Rechner a where rechnen :: a -> Double class Eq a where (==) :: a -> a -> Bool -- 保持原Rechner实例不变 instance Rechner (Ausdruck Double) where rechnen (Zahl1 a) = a rechnen (Add1 zahl1 zahl2) = rechnen zahl1 + rechnen zahl2 -- 给Double实现自定义Eq实例,复用Prelude的相等性逻辑 instance Eq Double where (==) = (Prelude.==) -- 添加必要约束:Rechner (Ausdruck a) 用于调用rechnen,Eq Double用于比较计算结果 instance (Prelude.Eq a, Rechner (Ausdruck a), Eq Double) => Eq (Ausdruck a) where (Zahl1 a) == (Zahl1 b) = a Prelude.== b (Add1 a1 a2) == (Add1 b1 b2) = rechnen (Add1 a1 a2) == rechnen (Add1 b1 b2) _ == _ = False -- 修改类型约束为自定义Eq isEqual :: Eq (Ausdruck a) => Ausdruck a -> Ausdruck a -> Bool isEqual l1 l2 = l1 == l2 firstNum = Add1 (Zahl1 1.5) (Zahl1 2.5) secondNum = Add1 (Zahl1 2.5) (Zahl1 1.5) call = isEqual firstNum secondNum -- 运行结果为True
关键修改说明
- 添加Double的Eq实例:直接复用Prelude内置的
==逻辑,满足比较rechnen返回值的需求。 - 扩展Eq实例约束:在
Eq (Ausdruck a)实例声明中添加Rechner (Ausdruck a)和Eq Double,明确告知编译器所需的上下文依赖。 - 修正isEqual类型约束:将原
Prelude.Eq a改为Eq (Ausdruck a),匹配自定义相等性检查的需求。
内容的提问来源于stack exchange,提问作者zeppal
相关产品推荐
相关产品推荐

