我有这个工作计划:
import Control.Monad.Random
data Tree = Node Tree Tree Tree Tree
| Leaf Bool
deriving (Show)
randomTree' :: (RandomGen a) => Int -> Rand a Tree
randomTree' 0 = do
r <- getRandom
return $ Leaf r
randomTree' depth = do
let d = depth-1
a <- randomTree' d
b <- randomTree' d
c <- randomTree' d
d <- randomTree' d
r <- getRandom
if r
then return $ Node a b c d
else randomTree' 0
randomTree1 :: Int -> Tree
randomTree1 seed = evalRand (randomTree' 4) (mkStdGen seed)
main = print $ randomTree1 1
但我不完全理解为什么这个版本失败并填满我的所有内存(用thunk?):
randomTree'' :: (RandomGen a) => Int -> Rand a Tree
randomTree'' depth = do
let d = depth-1
a <- randomTree'' d
b <- randomTree'' d
c <- randomTree'' d
d <- randomTree'' d
r1 <- getRandom
r2 <- getRandom
if depth > 0 && r1
then return $ Node a b c d
else return $ Leaf r2
由于懒惰,不应仅在需要时评估a
b
c
和d
吗?
谢谢!
答案 0 :(得分:4)
不幸的是,不,懒惰在这里无法帮助你:通过计算线程化的随机种子会增加数据依赖性,从而消除任何可能的懒惰。
具体而言:您检查通过r1
调用计算的getRandom
是否为True
。要知道这一点,必须在调用getRandom
时发现要使用的种子;并且要知道要使用哪个种子,必须首先对递归调用randomTree''
所要求的种子进行修改。由于递归调用永远不会在基本情况下触底,因此它们只会咀嚼越来越多的RAM,直到您的计算机窒息。无赖!