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]
g = do
n <- randomRIO (1,6) :: IO Integer
f <- g
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]
g = do
n <- randomRIO (1,6) :: IO Integer
f <- unsafeInterleaveIO g
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]
g = do
n <- randomRIO (1,6) :: IO Integer
!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.