Ich erstellen eine Haskell-Anwendung, die eine Zufallszahl in einer Endlosschleife generiert (nur wenn von einem Client angefordert). Allerdings sollte ich für diesen Zweck nur reine Funktionen verwenden. Ist es sicher, randomIO
mit unsafeperformIO
ohne drastische Stabilität oder Leistungsrisiko zu wickeln?Risiken der Verwendung von unsafeperformIO auf randomIO
Antwort
Jede Verwendung von unsafePerformIO
sollte durch einen Nachweis gerechtfertigt werden, dass der resultierende Wert immer noch rein ist. Die Strenge des Beweises liegt bei Ihnen und der Wichtigkeit der Arbeit. Zum Beispiel sollte dieser erbärmliche Gebrauch unsafePerformIO
und randomIO
sicher sein, weil Sie beweisen können, dass, wenn slowTrue
irgendetwas zurückgibt, es True
zurückgibt.
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
Die folgende verlockend Definition eines globalen, ist möglicherweise Zufallsvariablen nicht sicher:
rand :: Bool -> Int
rand True = unsafePerformIO randomIO
rand False = 0
Das Problem ist, dass der gleiche Ausdruck nun unterschiedliche Werte ergeben wird:
main = do
print (rand True)
print (rand True)
Drucke hier:
-7203223557365007318
-7726744474749938542
(zumindest wenn kompiliert ohne Optimierungen - aber das betont nur die Fragilität der unsachgemäßen Verwendung von unsafePerformIO
).
Das ist eine interessante Frage. Die Definition auf oberster Ebene 'unknown = unsafePerformIO randomIO' ist eigentlich sicher, wenn der Compiler den Körper von' unknown' nur einmal auswerten wird. Aber ich bin mir ziemlich sicher, dass der Compiler die Rechte hat, ihn zu inline und/oder mehrfach zu berechnen. – ony
Ich hatte das zuerst als mein Beispiel, aber ich konnte GHC nicht genug kitzeln, um das tatsächlich beobachtbar zu machen, daher dieses Beispiel. –
Sie sollten ['random'] (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:random) oder [' randomR'] verwenden (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:randomR) in reinem Code. –
NEIN! Du könntest 'unsafeInterleaveIO' rechtfertigen, aber nichts Zufall ist rein! –
@PhilipJF: "Nichts Zufälliges ist rein"? Ich würde sagen Dinge wie (Not-in-Place) Quicksort mit zufälliger Pivot sind reine Algorithmen in Ordnung: Die Zufälligkeit kann von außen nicht beobachtet werden, außer durch Performance-Variationen, die sowieso nur irgendeine Bedeutung in der 'IO'-Monade haben. – leftaroundabout