Data.List.iterate懒惰评估没有发生

时间:2016-04-19 17:58:45

标签: haskell

我有上述功能,但是当我调用它时,它会卡住,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 个答案:

答案 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是不变的,永远不会有理由进行评估,所以它实际上是被丢弃了。

如果您要使用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))

答案 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;))