我有上述功能,但是当我调用它时,它会卡住,Data.List.iterate会在不停止的情况下进行评估。
rp:: RandomGen g => g -> ([Int], g)
rp g = (map (\x -> (last (fst x))) lst , snd (next g))
where
lst = (Data.List.iterate id ([1], g_second))
(g_first, g_second) = (split g)
为什么会这样?
谢谢!
答案 0 :(得分:5)
虽然我不确定你想要用你的功能实现什么,但它没有停止的原因是因为你在无限列表上进行映射并且没有理由 停止。
无限列表源于您使用iterate
:
lst = (Data.List.iterate id ([1], g_second))
你在那里做的是创建一个包含无限数量的元组值([1], g_second)
的无限列表。这似乎是一个逻辑错误 - 元组列表没有变化;每个元素都是相同的,无穷大。需要说明的是,您正在构建的列表如下所示:
[([1], g_second), ([1], g_second), ([1], g_second), ([1], g_second)...]
g_second
是不变的,永远不会有理由进行评估,所以它实际上是被丢弃了。
如果您要使用take
或takeWhile
之类的内容,则可以强制该无限列表停止并返回已知数量的元素。但是,在此声明中使用map
:
map (\x -> (last (fst x))) lst
你所做的就是从元组中提取值1
并永远重复它。
由于您放弃了g_second
并且从不使用g_first
,因此您的功能与以下内容相同:
rp :: RandomGen g => g -> ([Int], g)
rp g = (repeat 1 , snd (next g))
答案 1 :(得分:2)
假设你想根据RandomGen g
生成一个无限的随机数列表,那么你可以使用Data.List.unfold
,因为它很适合next
:
> import System.Random
> import Data.List
> let rnds g = unfoldr (Just . next) g
> let rnds' = rnds (mkStdGen 0)
> take 3 rnds'
[2147482884,2092764894,1390461064]
BTW:是最后的g
丢失了 - 但为了得到这个,你必须首先生成无限列表......这似乎不太可能( plus 它不适合unfoldr
;))