Haskell列表推导式类型错误:无法匹配Float与Int类型的优雅解决办法
错误根因
你的hyp函数返回Float类型,而[1..n]的元素是Int类型,Haskell的elem函数要求待匹配元素与列表元素类型一致,因此触发类型错误。你修改为[1..fromIntegral n]的方案虽然能通过编译,但存在两个明显缺陷:
- 生成Float列表的额外开销
- 浮点数精度误差可能导致整数判断错误(例如大数值开根号后出现
.9999999999或.0000000001的偏差)
最优解决方案
完全规避浮点数比较逻辑,改用整数验证实现,全程无类型冲突,性能和稳定性更好:
pyths :: Int -> [(Int, Int, Int)] pyths n = [(x, y, z) | x <- [1..n], y <- [x..n], let sumSq = x*x + y*y, let z = floor $ sqrt $ fromIntegral sumSq, z * z == sumSq, z <= n]
逻辑说明:
- 先计算
x和y的平方和sumSq - 计算
sumSq的整数平方根z - 验证
z的平方是否等于sumSq(确保sumSq是完全平方数),同时验证z在[1..n]范围内 - 所有条件满足则返回三元组
(x,y,z)
沿用原有写法的简化方案
如果不想改动之前的isqrt、hyp函数定义,可以直接将斜边结果转为整数后验证,不需要生成浮点区间列表:
pyths :: Int -> [(Int, Int, Int)] pyths n = [(x, y, z) | x <- [1..n], y <- [x..n], let z = truncate (hyp x y), z*z == x*x + y*y, z <= n]
内容的提问来源于stack exchange,提问作者Nevermore
相关产品推荐
相关产品推荐

