1 -_-
1 -_-

Reputation: 183

How does the `randoms` function in Haskell work?

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

Answers (2)

Carcigenicate
Carcigenicate

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 yielding 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

Michal Charemza
Michal Charemza

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

Related Questions