Haskell实现Collatz猜想代码报错:错误排查与报错信息解读方法
代码错误原因
- 类型约束冲突:你定义的类型签名要求输入参数同时满足
Integral和Fractional两个类型类约束,而Haskell标准库中不存在同时实现这两个类型类的类型:Integral是整数类型的抽象,Fractional是支持浮点除法的类型的抽象,二者互斥,编译器找不到符合约束的类型,自然会报类型歧义错误。 - 除法运算符使用错误:你在处理偶数分支时用了
/运算符,这个运算符仅属于Fractional类型类,而你需要对整数做整除,应该使用div或者quot运算符,这两个才属于Integral类型类。 - 额外逻辑隐患:你没有对输入为0或负数的情况做边界处理,不过这不属于本次报错的直接原因。
报错信息解读思路
这类类型歧义报错核心看三个点:
- 先看报错开头的
Could not deduce XXX arising from a use of XXX:这里明确告诉你编译器没法推导出你调用的函数要求的类型约束。 - 再看
The type variable XXX is ambiguous:说明编译器没法确定你传入的字面量(这里是5)到底该用哪个具体类型,因为没有任何标准类型符合你函数要求的Integral + Fractional的约束。 - 最后看列出来的
potential instances:这里列的是编译器能找到的所有可能符合部分约束的类型,你会发现这些类型要么只实现了Integral(Integer、Int、Word),要么只实现了Fractional(Double、Float),没有同时满足的,自然没法匹配。
修正后的代码
collatzConjecture :: Integral a => a -> Int collatzConjecture x = collatzConjecture' x 0 where collatzConjecture' 1 n = n collatzConjecture' x n | odd x = collatzConjecture' (x*3+1) (n+1) | even x = collatzConjecture' (x `div` 2) (n+1)
如果需要更泛型的返回值,可以把返回值类型改成Integral b => b即可。测试调用collatzConjecture 5会返回正确结果5。
内容的提问来源于stack exchange,提问作者Yachara
相关产品推荐
相关产品推荐

