2013-04-25 3 views
5

無限ループで乱数を生成するHaskellアプリケーションを作成しています(クライアントから要求された場合のみ)。しかし、私はその目的のために純粋な関数を使うべきです。劇的な安定性やパフォーマンスのリスクなしにrandomIOunsafeperformIOに改行するのは安全ですか?randomIOでunsafeperformIOを使用する場合のリスク

+5

['random'](http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:random)または[' randomR']を使用してください。 (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:randomR)を参照してください。 –

+1

NO!あなたは 'unsafeInterleaveIO'を正当化できるかもしれませんが、ランダムなものは純粋ではありません! –

+6

@PhilipJF:「無作為なものは純粋ではない」?私はランダムなピボットのクイックソートは純粋なアルゴリズムだと言っています。ランダム性はパフォーマンスのバリエーションを除いて外部からは見ることができません。パフォーマンスのバリエーションは、IOモナドでは意味がありません。 – leftaroundabout

答えて

12

unsafePerformIOの使用は、結果値がまだ純粋であるという証拠によって正当化されるべきです。証拠の厳格さはあなた次第であり、仕事の重要性です。例えば、この哀れな使用unsafePerformIOrandomIOは、となるので、安全でなければなりません。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 

グローバル、おそらく確率変数の以下の魅力的な定義は安全ではありません。

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

プリント:

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

問題は、同じ式が今異なった値が得られるということですここに:

-7203223557365007318 
-7726744474749938542 

(少なくとも、最適化なしでコンパイルされたとき - しかし、それはちょうどunsafePerformIOの不適切な使用の脆弱性を強調する)。

+0

これは興味深い質問です。トップレベルの定義 'unknown = unsafePerformIO randomIO'は、コンパイラが' unknown'の本体を一度だけ評価する場合、実際には安全です。しかし、私は、コンパイラがそれをインライン化し、そして/または何度も計算する権利を持っていることを確信しています。 – ony

+2

私はこれを私の例として最初に持っていましたが、私はそれを実際に観測可能にするのに十分なほどGHCをくすぐることはできませんでした。 –

関連する問題