Understanding unsafeInterleaveIO
July 14, 2015While answering some question in StackOverflow, I came across this following piece of code which won’t terminate:
import System.Random
g :: IO [Integer]
= do
g <- randomRIO (1,6) :: IO Integer
n <- g
f return (n : f)
So, now we can see why this piece of computation doesn’t terminate.
The line f <- g
specifically makes it go on and on. Now can we make
it work using unsafeInterleaveIO
:
import System.Random
import System.IO.Unsafe (unsafeInterleaveIO)
g :: IO [Integer]
= do
g <- randomRIO (1,6) :: IO Integer
n <- unsafeInterleaveIO g
f return (n : f)
In a sample GHCI session:
λ> g >>= \x -> return $ take 5 $ x
[1,2,2,5,6]
With a Bang!, we can again make it non-terminating:
{-#LANGUAGE BangPatterns#-}
import System.Random
import System.IO.Unsafe (unsafeInterleaveIO)
g :: IO [Integer]
= do
g <- randomRIO (1,6) :: IO Integer
n !f <- unsafeInterleaveIO g
return (n : f)
And in GHCI:
λ> g >>= \x -> return $ take 5 $ x
C-c C-c Interrupted.
Note that I still believe it’s a bad option to use
unsafeInterleaveIO
unless there is no other go. But I find this
example as a nice way to understand the working of unsafeInterleaveIO
.