Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using global random generator via getStdGen in Haskell

I've just started learning Haskell with the enjoyable reading of "Learn you a Haskell for great Good!" and there is an example in the book which doesn't make sense to me. It says that the following code would output the same random string twice:

main = do
    gen <- getStdGen
    putStrLn $ take 20 (randomRs ('a','z') gen)
    gen2 <- getStdGen
    putStrLn $ take 20 (randomRs ('a','z') gen2)

On the other hand, if the very same program is called twice it would undoubtedly yield different outputs. Moreover, that doesn't seem consistent if I compare it to the code below which yields different values of s1 and s2:

main = do
    s1 <- getLine
    s2 <- getLine
    putStrLn s1
    putStrLn s2

I'm wondering how the above two examples are different.

like image 992
the-happy-hippo Avatar asked Jan 11 '23 07:01

the-happy-hippo


1 Answers

This is just a specific property of getStdGen: unlike getLine, it is not an "effectful" IO action, but just accesses the same default random-generator state each time you evaluate it. It is thus almost a pure function, but since it'll be different between different program runs (and indeed within the same run, if you explicitly modify with setStdGen), they've nevertheless put it in the IO monad.

Perhaps a good analogy is this:

main = do
    file <- readFile "/etc/bash.bashrc"  -- or any other persistent system file
    putStrLn $ head (lines file)
    file2 <- readFile "/etc/bash.bashrc"
    putStrLn $ head (lines file2)
like image 96
leftaroundabout Avatar answered Jan 28 '23 13:01

leftaroundabout