更新:好的,这个问题可能非常简单.
q <- mapM return [1..]
Run Code Online (Sandbox Code Playgroud)
为什么这永远不会回来?
mapM是不是懒得处理无限列表?
下面的代码挂起.但是,如果我用线B替换A线,它就不会再挂起了.或者,如果我在A行之前加上"splitRandom $",它也不会挂起.
Q1是:mapM不是懒惰的吗?否则,为什么用线B替换A行"修复此"代码?
Q2是:为什么前面的A行与splitRandom"解决"了这个问题?
import Control.Monad.Random
import Control.Applicative
f :: (RandomGen g) => Rand g (Double, [Double])
f = do
b <- splitRandom $ sequence $ repeat $ getRandom
c <- mapM return b -- A
-- let c = map id b -- B
a <- getRandom
return (a, c)
splitRandom :: (RandomGen g) => Rand g a -> Rand g a
splitRandom code = evalRand code <$> getSplit
t0 …Run Code Online (Sandbox Code Playgroud) 以下程序正确终止:
import System.Random
randomList = mapM (\_->getStdRandom (randomR (0, 50000::Int))) [0..5000]
main = do
randomInts <- randomList
print $ take 5 randomInts
Run Code Online (Sandbox Code Playgroud)
运行:
$ runhaskell test.hs
[26156,7258,29057,40002,26339]
Run Code Online (Sandbox Code Playgroud)
但是,为它提供无限列表,程序永远不会终止,并且在编译时,最终会产生堆栈溢出错误!
import System.Random
randomList = mapM (\_->getStdRandom (randomR (0, 50000::Int))) [0..]
main = do
randomInts <- randomList
print $ take 5 randomInts
Run Code Online (Sandbox Code Playgroud)
跑步,
$ ./test
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
Run Code Online (Sandbox Code Playgroud)
我希望getStdRandom每次从列表中选择一个项目时,程序都会懒洋洋地评估,在完成5次之后完成.为什么要评估整个列表?
谢谢.
有没有更好的方法来获得无限的随机数列表?我想将此列表传递给纯函数.
编辑:更多阅读揭示了该功能
randomList r = do g <- getStdGen
return …Run Code Online (Sandbox Code Playgroud)