将函数应用于相等值时的结果不同

时间:2010-03-31 14:37:24

标签: haskell tuples equality

我只是在挖掘Haskell,我开始尝试计算文本中两个单词的Phi-Coefficient。但是,我遇到了一些我无法解释的非常奇怪的行为。

在删除所有内容后,我最终使用此代码重现问题:

let sumTup = (sumTuples∘concat) frequencyLists
let sumFixTup = (138, 136, 17, 204)
putStrLn (show ((138, 136, 17, 204) == sumTup))
putStrLn (show (phi sumTup))
putStrLn (show (phi sumFixTup))

输出:

True
NaN
0.4574206676616167

因此虽然sumTupsumFixTup显示相同,但​​传递给phi时其行为会有所不同。

phi的定义是:

phi (a, b, c, d) = 
    let dividend = fromIntegral(a * d - b * c)
        divisor = sqrt(fromIntegral((a + b) * (c + d) * (a + c) * (b + d)))
    in dividend / divisor

1 个答案:

答案 0 :(得分:8)

这可能是整数溢出的情况。传递到除数中fromIntegral的值为3191195800,大于32位有符号Int可以容纳的值。

在ghci(或您正在使用的任何内容)中,使用

:t sumTup
:t sumFixTup

查看这些变量的类型。我猜你会发现sumTup(Int, Int, Int, Int)(溢出)而sumFixTup(Integer, Integer, Integer, Integer)(不会溢出)。

编辑:第二个想法,Ints的元组不能等于整数元组。即便如此,我认为ghci会将sumFixTup的类型修改为整数元组,而sumTup可能有(Num a) => (a, a, a, a)(Integral a) => (a, a, a, a)形式的类型,取决于定义它的功能。

然后Ghci会将它们转换为整数以与sumFixTup进行比较,但在计算phi中的除数时可能会将它们转换为Ints,从而导致溢出。


另一个编辑:KennyTM,你是对的一半:

Prelude> :t (1,2,3,4)
(1,2,3,4) :: (Num t, Num t1, Num t2, Num t3) => (t, t1, t2, t3)
Prelude> let tup = (1,2,3,4)
Prelude> :t tup
tup :: (Integer, Integer, Integer, Integer)

所以对于问题中给出的例子:

putStrLn (show ((138, 136, 17, 204) == sumTup))

文字(138, 136, 17, 204)被推断为匹配Int的{​​{1}}元组,并且它们相等。

sumTup

putStrLn (show (phi sumTup)) sumTup组成,导致溢出,如上所述。

Int

putStrLn (show (phi sumFixTup)) sumFixTup组成,给出了正确的结果。请注意,IntegersumTup从未直接进行过比较,因此我之前的编辑是基于误读。<​​/ p>