Reputation: 183
I'm following the Learn You A Haskell book to learn Haskell, and I am having trouble understanding the randoms
function. The book defines the function as:
randoms' :: (RandomGen g, Random a) => g -> [a]
randoms' gen = let (value, newGen) = random gen in value:randoms' newGen
Now the way I see this function is that it calls itself recursively and appends the return value to the list value
. What I don't understand is how the function returns because every time it just calls itself with a new random seed!
Upvotes: 2
Views: 188
Reputation: 45806
As a crude comparison, instead of trying to think of how an infinite list could be returned, consider how a Python generator is capable of "returning" an infinite list: by yield
ing one element at a time, as they're required.
The entire list isn't returned at once. Each element is evaluated as it's needed, and the function only recurses as it needs to.
Note, I'm not claiming Haskell's laziness works the same way as Python's generators, but it may be a helpful comparison to keep in mind when thinking about functions like these.
See the other answer to get an explanation of why this is happening.
Upvotes: 5
Reputation: 27052
I think the confusing part might be the use of :
in the return value.
value:randoms' newGen
This is a list, with the first item of value
, and the rest of the list is what is returned by the recursive call to randoms' newGen
.
What I don't understand is how the function returns because every time it just calls itself with a new random seed!
Because of laziness, it will only call itself if you try to access the second (or later) item of the returned list. This list isn't, and couldn't be in memory, at once. Lists in Haskell are more like recipes... until you try to access an element, Haskell doesn't try to work out what it is.
Upvotes: 7