
[英]Overflow problems in dealing with IO and MonadRandom and chained computations
[英]MonadRandom: why stack overflow happens?
这个问题肯定是针对stackoverflow.com的
这是样本
module Main where
import Control.Monad.Random
import Control.Exception
data Tdata = Tdata Int Int Integer String
randomTdata :: (Monad m, RandomGen g) => RandT g m Tdata
randomTdata = do
a <- getRandom
b <- getRandom
c <- getRandom
return $ Tdata a b c "random"
manyTdata :: IO [Tdata]
manyTdata = do
g <- newStdGen
evalRandT (sequence $ repeat randomTdata) g
main = do
a <- manyTdata
b <- evaluate $ take 1 a
return ()
编译后返回
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it
怎么会发生? MonadRandom是不是很懒?还是其他呢? 以及在这种情况下如何定义堆栈溢出的原因?
出现问题是因为您正在将IO
manyTdata
到manyTdata
函数中。 monad变压器最终成为RandT g IO Tdata
类型。 因为你的无限列表中的每个元素可以由IO
操作,返回的无限列表的整体manyTdata
必须完全评估之前,该函数可以返回任何结果。
最简单的解决方案是使用Rand
而不是RandT
,因为使用RandT
在这里并不是真正有用的。 你也可以改变基单子到类似的Identity
通过改变单子manyTdata
到
manyTdata :: IO [Tdata]
manyTdata = do
g <- newStdGen
return $ runIdentity $ evalRandT (sequence $ repeat randomTdata) g
这将在有限的时间内终止。 与堆栈大小有关的错误仅是递归扩展IO
操作列表的结果。 您的代码说要对所有这些动作进行排序,因此必须全部执行,这与懒惰无关。
除了使用randomTdata
,还需要考虑其他randomTdata
,请考虑使Tdata
成为Random
类的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.