2016-04-19 48 views
0

我有上述功能,但是当我调用它时,它会卡住,Data.List.iterate的计算没有停止。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) 

为什么会发生这种情况?

谢谢!

+2

什么是'rp'应该做的?如果它应该创建一个随机列表,则应该传入随机列表的期望长度... – Alec

+0

它假设首先结束。不是吗? –

+0

元组中的第一个参数是无限列表'[1 ..]'因此我的问题是关于长度。 – Alec

回答

5

虽然我不完全确定你想用你的函数实现什么,但它不停止的原因是因为你正在映射一个无限列表并给它没有理由 stop。

无限名单起源于你使用的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是不变的,从来没有得到一个理由来评价,所以在本质上,丢弃。

如果您要使用类似taketakeWhile的东西,可以强制该无限列表停止并返回已知数量的元素。然而,在这个语句中使用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)) 
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缺失 - 但要得到这个,你将不得不首先生成无限列表... ...这似乎不太可能(它不适合unfoldr很好;))