You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修改说明

  1. 添加Double的Eq实例:直接复用Prelude内置的==逻辑,满足比较rechnen返回值的需求。
  2. 扩展Eq实例约束:在Eq (Ausdruck a)实例声明中添加Rechner (Ausdruck a)和Eq Double,明确告知编译器所需的上下文依赖。
  3. 修正isEqual类型约束:将原Prelude.Eq a改为Eq (Ausdruck a),匹配自定义相等性检查的需求。

内容的提问来源于stack exchange,提问作者zeppal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:30:44