这个问题肯定适用于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不是懒惰还是其他什么?如何在这种情况下定义堆栈溢出的原因?
答案 0 :(得分:4)
出现此问题是因为您正在IO
功能中构建manyTdata
。
monad变换器最终为RandT g IO Tdata
类型。因为每个元素
您的无限列表可以包含IO
个动作,无限列表的全部内容
在函数返回之前,manyTdata
返回的完全必须被评估
任何结果。
最简单的解决方案是使用Rand
代替RandT
,就像使用转换器一样
反正在这里并不是真的有用;你也可以将基础monad更改为类似的东西
通过将Identity
更改为
manyTdata
monad
manyTdata :: IO [Tdata]
manyTdata = do
g <- newStdGen
return $ runIdentity $ evalRandT (sequence $ repeat randomTdata) g
哪个会在有限的时间内终止。有关堆栈大小的错误
只是递归扩展您的IO
操作列表的结果。你的代码说要对所有这些动作进行排序,所以它们都必须被执行,它与懒惰无关。
要考虑的其他事情,而不是使用randomTdata
使Tdata
成为Random
类的实例。