Haskell中的“randoms”函数是如何工作的?

Haskell中的“randoms”函数是如何工作的?,haskell,Haskell,我正在按照这本书学习Haskell,我在理解randoms函数时遇到了困难。本书将功能定义为: randoms' :: (RandomGen g, Random a) => g -> [a] randoms' gen = let (value, newGen) = random gen in value:randoms' newGen 现在,我看到这个函数的方式是,它递归地调用自己,并将返回值附加到列表value。我不明白的是函数是如何返回的,因为每次它只是用一个新的随

我正在按照这本书学习Haskell,我在理解
randoms
函数时遇到了困难。本书将功能定义为:

randoms' :: (RandomGen g, Random a) => g -> [a]  
randoms' gen = let (value, newGen) = random gen in value:randoms' newGen    

现在,我看到这个函数的方式是,它递归地调用自己,并将返回值附加到列表
value
。我不明白的是函数是如何返回的,因为每次它只是用一个新的随机种子调用自己

我认为令人困惑的部分可能是在返回值中使用了

value:randoms' newGen 
这是一个列表,第一项是
value
,其余部分是递归调用
randoms'newGen
返回的内容

我不明白的是函数是如何返回的,因为每次它只是用一个新的随机种子调用自己


由于懒惰,只有当您尝试访问返回列表的第二个(或更高版本)项时,它才会调用自己。此列表不是,也不可能立即出现在内存中。Haskell中的列表更像是食谱。。。在尝试访问一个元素之前,Haskell并不试图找出它是什么。

< P>作为一个粗略的比较,而不是试图考虑无限列表的返回,考虑Python生成器如何能够“返回”一个无限列表:按<代码>屈服< /代码>一次一个元素,因为它们是必需的。 不会立即返回整个列表。每个元素都会根据需要进行求值,函数只会根据需要进行递归

请注意,我并不是说Haskell的懒惰与Python的生成器的工作方式相同,但在考虑类似的函数时,记住它可能是一个有用的比较


请参阅另一个答案,以了解发生这种情况的原因

不,因为懒惰,在需要时才计算尾部。我记不清具体的函数,但是如果它创建了一个懒惰的无限随机数列表,你可以从无限列表中获取一些元素。注意函数不会一次计算所有值;它仅根据需要生成值。查看
repeat
函数,查看另一个例子。@1-\您的想法太严格了。你知道Python生成器是什么吗?@1-u-好的,很好。我想说的是,当使用无限列表时,您可以在一次生成一个值,而不是一次返回整个列表。我强烈建议深入研究懒惰,并习惯它,因为哈斯凯尔广泛地使用它。@1-\n我不知道我是否能写出一个好的解释,因为我使用哈斯凯尔已经有一段时间了,这是一个很难深入研究的话题。这是我所能想到的最好的比较,可能有助于改变你的观点。对我来说,一个相关的、有用的见解是,Haskell中的列表在用作数据结构时不是很好(如果你想存储一系列元素,一个
向量
或其他更好的东西),但它们是优秀的控制结构,在其他语言中,其行为或多或少类似于(记忆的)迭代器和生成器。