包含在函数中的Haskell随机生成器始终返回相同的值

Ade*_*ick 1 random haskell

我们假设我在GHCi中执行以下代码:

[unsafePerformIO (randomRIO (0,1)) | _ <- [1..10]].
Run Code Online (Sandbox Code Playgroud)

[1,1,0,0,1,0,0,0,0,1]每次执行此操作时,结果可能看起来都不同.现在假设我定义了以下函数:

f :: Int
f = unsafePerformIO (randomRIO (0,1))
Run Code Online (Sandbox Code Playgroud)

并试着打电话:

[f | _ <- [1..10]].
Run Code Online (Sandbox Code Playgroud)

结果总是如此[0,0,0,0,0,0,0,0,0,0].如果我只是打一个电话f,它总是返回0.暂且说我不应该把IO扔掉,我做错了什么?

Cir*_*dec 7

你做错了就是使用unsafePerformIO,特别是当你知道它不会是一个功能时 - 它会为相同的输入提供不同的输出.

你的邪恶使用的原因unsafePerformIO并不像你想象的那样f,这不是一个功能,它是以常量的应用形式.它只会被评估一次,并且每次都是相同的.您可以通过将其定义更改为来查看此内容

f :: Int
f = unsafePerformIO (putStrLn "generating" >> randomRIO (0,1))
Run Code Online (Sandbox Code Playgroud)

"生成"只打印一次.

写一个邪恶的"功能",写

g :: a -> Int
g a = unsafePerformIO (randomRIO (0,1))

print [g x | x <- [1..10]]
Run Code Online (Sandbox Code Playgroud)

x即使它们具有相同的值,也将对每个进行一次评估.你可以通过评估看出这是多么邪恶

print [g x | x <- [1,1,1,1,1,1,1]]
Run Code Online (Sandbox Code Playgroud)

"功能"对同一输入有不同的输出!把所有东西都放在Unsafe一边,直到你确定你需要它并确定你理解它,然后无论如何都不管它.