Риски использования unsafeperformIO на randomIO

Я создаю приложение на Haskell, которое генерирует случайное число в бесконечном цикле (только по запросу клиента). Однако я должен использовать только чистые функции для этой цели. Это безопасно завернуть randomIO с unsafeperformIO без какой-либо радикальной стабильности или риска для производительности?

2 ответа

Решение

Любое использование unsafePerformIO должно быть обосновано доказательством того, что полученное значение все еще является чистым. Строгость доказательства зависит от вас и важности работы. Например, это жалкое использование unsafePerformIO а также randomIO должен быть безопасным, потому что вы можете доказать, что когда slowTrue вернет что-нибудь, вернется 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

Следующее заманчивое определение глобальных, возможно, случайных переменных небезопасно:

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

Проблема в том, что одно и то же выражение теперь будет давать разные значения:

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

печатает здесь:

-7203223557365007318
-7726744474749938542

(по крайней мере, когда компилируется без оптимизации - но это только подчеркивает хрупкость неправильного использования unsafePerformIO).

Я создаю приложение на Haskell, которое генерирует случайное число в бесконечном цикле (только по запросу клиента). Однако я должен использовать только чистые функции для этой цели. Безопасно ли оборачивать randomIO с unsafeperformIO без какой-либо значительной стабильности или риска для производительности?

Помимо производительности (без риска) или стабильности (небольшой риск), учтите также тот факт, что вы пишете неканонический язык Haskell без уважительной причины. Если вы воспользуетесь этим подходом, ваш код будет трудно поддерживать кому-либо еще.

Другие вопросы по тегам