包装到函数中的Haskell随机生成器始终返回相同的值
假设我在GHCi中执行以下代码:包装到函数中的Haskell随机生成器始终返回相同的值,haskell,random,Haskell,Random,假设我在GHCi中执行以下代码: [unsafePerformIO (randomRIO (0,1)) | _ <- [1..10]]. 并尝试拨打: [f | _ <- [1..10]]. [f|up>unsafePerformIO不会使函数变得非纯 改为使用序列: sequence [randomRIO (0,1) | _ <- [1..10]] > [0,1,0,0,1,1,0,1,0,1] sequence[randomRIO(0,1)|u [0,1,0
[unsafePerformIO (randomRIO (0,1)) | _ <- [1..10]].
并尝试拨打:
[f | _ <- [1..10]].
[f|up>unsafePerformIO
不会使函数变得非纯
改为使用序列
:
sequence [randomRIO (0,1) | _ <- [1..10]]
>
[0,1,0,0,1,1,0,1,0,1]
sequence[randomRIO(0,1)|u
[0,1,0,0,1,1,0,1,0,1]
unsafePerformIO
不会使函数变得非纯
改为使用序列
:
sequence [randomRIO (0,1) | _ <- [1..10]]
>
[0,1,0,0,1,1,0,1,0,1]
sequence[randomRIO(0,1)|u
[0,1,0,0,1,1,0,1,0,1]
错误之处在于使用了unsafePerformIO
,尤其是当您知道它不是一个函数时,对于相同的输入,它将有不同的输出
您使用的unsafePerformIO
之所以不能按预期工作,是因为f
不是一个函数,而是一个函数。它将只计算一次,每次都是相同的。您可以通过将其定义更改为
f :: Int
f = unsafePerformIO (putStrLn "generating" >> randomRIO (0,1))
“生成”仅打印一次
要使一个邪恶的“功能”,写
“功能”对于相同的输入有不同的输出!将不安全
中的所有内容都放在一边,直到您确定需要并理解它,然后再放在一边。您所做的错误是使用unsafePerformIO
,特别是当您知道它不是一个函数时-它将为ame输入
您使用的unsafePerformIO
之所以不能按预期工作,是因为f
不是一个函数,而是一个函数。它将只计算一次,每次都是相同的。您可以通过将其定义更改为
f :: Int
f = unsafePerformIO (putStrLn "generating" >> randomRIO (0,1))
“生成”仅打印一次
要使一个邪恶的“功能”,写
对于相同的输入,“函数”有不同的输出!将Unsafe
中的所有内容都放在一边,直到你确定你需要它并理解它,然后再放在一边。unsafePerformIO
不要让函数变得非纯。使用序列[randomiro(0,1)|使用unsafePerformIO
是一个很大的“不要”在Haskell中。除非您确切知道自己在做什么,并且能够确保调用unsafePerformIO
将产生纯函数,否则不要使用它。对于随机数生成,您必须使生成步骤在IO
(或者在我喜欢的MonadRandom
monad中,您需要安装MonadRandom
包)。unsafePerformIO
不要使函数非纯。使用sequence[randomRIO(0,1)|使用unsafePerformIO
是一个很大的“不要”在Haskell中。除非您确切知道自己在做什么,并且能够确保调用unsafePerformIO
将产生纯函数,否则不要使用它。对于随机数生成,您必须使生成步骤在IO
(或者在MonadRandom
monad中,我更喜欢它,您需要安装MonadRandom
包)。不使函数纯,您想说吗?@AdelNick,纯函数在相同的输入上总是有相同的输出。因此,您的f=unsafePerformIO(randomiro(0,1))
仍然是纯的,即使有unsafePerformIO
@AdelNick要澄清这一点,使unsafePerformIO
如此不安全的是,编译器在大多数情况下基本上忽略了它的杂质,并将使用它的表达式视为纯的。这意味着,如果是纯表达式,它可以选择不重新计算它不需要重新评估,并且可以选择将其内联到其使用站点中,以使其得到比您想要的更多的评估。您想说的是,不使函数纯吗?@AdelNick,纯函数在相同的输入上总是有相同的输出。因此,您的f=unsafePerformIO(randomRIO(0,1))
仍然是纯的,即使有unsafePerformIO
@AdelNick要澄清这一点,使unsafePerformIO
如此不安全的是,编译器在大多数情况下基本上忽略了它的杂质,并将使用它的表达式视为纯的。这意味着,如果是纯表达式,它可以选择不重新计算它不需要重新评估,并且可以选择在其使用站点中内联它,以便得到比您想要的更多的评估。感谢详细的回答谢谢详细的回答
print [g x | x <- [1,1,1,1,1,1,1]]