Risks of using unsafeperformIO on randomIO

I am creating a Haskell application that generates a random number in an infinite loop (only on client request). However, for this purpose I should use only pure functions. Is it safe to wrap randomIOusing unsafeperformIOwithout any serious stability or performance risk?

+5
source share
1 answer

Any use unsafePerformIOshould be justified by proving that the value obtained remains clean. The rigor of the proof is up to you and the importance of the work. For example, this is miserable use unsafePerformIOand randomIOshould be safe, because you can prove that when it slowTruereturns something, 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 global, possibly random variables is unsafe:

rand :: Bool -> Int
rand True = unsafePerformIO randomIO 
rand False = 0

The problem is that the same expression will now give different meanings:

main = do
    print (rand True)
    print (rand True)

prints here:

-7203223557365007318
-7726744474749938542

(at least when compiling without optimization - but it just emphasizes the fragility of misuse unsafePerformIO).

+12
source

All Articles