System.Random表现得非常奇怪; 显示的数字不是正在操作的数字

use*_*038 3 random haskell

我需要为测试目的生成一些随机数.我之前从未使用过Data.Random.我需要做很多测试,我不知道提前需要的数量,但我知道它们应该落入某个界限.我写了这个函数:

import System.Random

f k = (\(x,y) -> x*y < (10^k) && x*y >0 )

rands n g k = take n $ filter (\(x,y) -> x*y < (10^k) && x*y >0 ) (zip a b) 
    where a = randomRs (1::Int, 10^k-1) ga 
          b = randomRs (1::Int, 10^k-1) gb
          (ga, gb) = split $ mkStdGen g
Run Code Online (Sandbox Code Playgroud)

并开始使用它生成的数字来测试事物.使用此功能时我开始注意到奇怪的事情:

testRands n k = do
    g1 <- randomIO
    g2 <- randomIO
    let r = rands n (mkStdGen g1, mkStdGen g2) k
    putStrLn $ show r 
    putStrLn $ show $ map (\(x,y) -> x*y < 10^k && x*y >0) r  
    putStrLn $ show $ map (\(x,y) -> x*y) r
    putStrLn $ show $ maximum $ map (\(x,y) -> x*y) r

*Main> testRands 4 7
[(6193574,9385226),(9634973,5475375),(5070277,7408626),(3801396,5652588)]
[True,True,True,True]
[4353660,6993107,2038586,4030960]
6993107
Run Code Online (Sandbox Code Playgroud)

然后我复制它生成的数字并将它们粘贴回GHCI并在所有这些上调用完全相同的谓词函数:

*Main> map (f 7) [(6193574,9385226),(9634973,5475375),(5070277,7408626),(3801396,5652588)]
[False,False,False,False]
Run Code Online (Sandbox Code Playgroud)

这没有任何意义,我甚至不知道从哪里开始尝试修复它.

kos*_*kus 8

在您的程序中,您将Int在以下行中显式生成类型的值:

where a = randomRs (1::Int, 10^k-1) ga 
      b = randomRs (1::Int, 10^k-1) gb
Run Code Online (Sandbox Code Playgroud)

如果您使用的是32位计算机,则生成的数字的乘法可能会导致溢出.例如:

> 6193574 * 9385226 :: Int
4353660
Run Code Online (Sandbox Code Playgroud)

但是,文字本身是超载的.因此,如果将它们粘贴到GHCi中,那么它们将被默认为(无界)Integer类型,它们不会溢出:

> 6193574 * 9385226 :: Integer
58128091737724
Run Code Online (Sandbox Code Playgroud)

这解释了应用谓词的困难结果.

因此要么生成Integer而不是Int,要么添加一个类型注释,说明您传递的列表[Int]而不是[Integer]使结果匹配.