minimum函数存在Bug?Haskell列表最小值计算异常问询
问题分析:
minimum与foldr min结果不一致的原因 这种情况最可能的原因有两个,我们逐一拆解分析:
1. 列表中存在违反Ord定律的元素(最常见是NaN)
Haskell里Double/Float的Ord实例遵循IEEE 754标准,NaN(非数字)和任何值的比较都会返回False,这会直接打乱min/max的正常逻辑:
minimum底层是用foldl实现的,从列表第一个元素开始,从左到右遍历比较- 如果列表中途出现NaN,后续的
min操作会一直保留NaN(因为min x NaN和min NaN x都会返回NaN) - 不过你提到
minimum返回的是0.100878而非NaN,所以这个可能性相对较低,但可以用下面的代码快速验证:-- 检查列表中是否存在NaN any isNaN mins
2. 元素的Ord实例被反转(比如使用Down类型)
如果你的mins列表里的元素不是普通Double,而是被包装在Down类型中(或是自定义了反转排序的Ord实例),就会出现这种“最小值返回较大值、最大值返回较小值”的反常情况:
Down类型的Ord实例是反转的:compare (Down a) (Down b) = compare b a- 此时
minimum会返回原数据里的最大值,maximum会返回原数据里的最小值 - 而
foldr min 100000 mins因为初始值是普通数值(会被自动包装为Down 100000),反向遍历反而能正确找到原数据中的最小值
验证方法
先检查mins的类型:
:t mins
如果输出是[Down Double]或类似自定义反转类型,那就是这个问题。
解决方案
- 如果是NaN问题:先过滤掉NaN再调用
minimum/maximum:minimum (filter (not . isNaN) mins) - 如果是
Down或反转Ord问题:要么直接使用原数值类型,要么在调用minimum前解开包装:-- 解开Down包装 minimum (map getDown mins)
内容的提问来源于stack exchange,提问作者Stéphane Laurent
相关产品推荐
相关产品推荐

