Risks of using unsafeperformIO on randomIO
haskell, random, unsafe-perform-io
Solution
Any use of `unsafePerformIO` should be justified by a proof that the resulting value is still pure. The rigour of the proof is up to you and the importance of the work. For example, this pathetic use `unsafePerformIO` and `randomIO` should be safe, because you can prove that when `slowTrue` returns anything, it will return `True`.
import System.Random
import System.IO.Unsafe
import Data.Int
slowTrue = unsafePerformIO $ go
where
go = do
x1 <- randomIO
x2 <- randomIO
if ((x1 :: Int16) == x2) then return True else go
The following tempting definition of a global, possibly random variables is not safe:
rand :: Bool -> Int
rand True = unsafePerformIO randomIO
rand False = 0
The problem is that the same expression will now yield different values:
main = do
print (rand True)
print (rand True)
prints here:
-7203223557365007318
-7726744474749938542
(at least when compiled without optimizations – but that just stresses the fragility of inappropriate use of `unsafePerformIO`).
Problem
I am creating a Haskell application that generates a random number on an infinite loop (only when requested by a client). However, I should only use pure functions for that purpose. Is it safe to wrap `randomIO` with `unsafeperformIO` without any drastic stability or performance risk?