Haskell で乱数を利用する方法

Haskell で乱数を利用する方法を調べては忘れ,調べては忘れを繰り返すのでメモする.一様乱数で十分な場合はモジュール System.Random, それ以外の正規分布等も使用したい場合はモジュール Data.Random を使用する.

Uniform Random Numbers

モジュール System.Random を使用する.区間 [0,1] の一様乱数を n 個を得るには次のコード.

import System.Random

rs :: Int -> IO [Double]
rs n = replicateM n $ randomRIO (0,1)

Other Random Numbers

モジュール Data.Random を使用 random-fu を使用するのが楽だと思う.次でインストールできる.

cabal install random-fu

速度は他のhaskellの乱数ライブラリと同等だが,C実装よりは遅いらしい.まあ,そうだろ.

平均 0, 分散 1 の正規分布に従う乱数を n 個得るには次のコード.

import Data.Random

rs :: Int -> IO [Double]
rs n = replicateM n . sample $ StdNormal

モジュール Data.Random をインポートすると分布として一様分布 Uniform, 標準正規分布 Stduniform, 正規分布 Normal, ガンマ分布 Gamma のみインポートされる.他の分布が必要な場合は,その都度 Data.Random.Distribution.<Dist-Name>import する必要がある.例えば指数分布を使いたい場合は次のように Exponential をインポートする.

import Data.Random.Distribution.Exponential

ちなみに Windows (GHC 7.8.2) だと下記のように表示され,実際に乱数の偏りが酷く,使いものにならない.

Warning: Couldn't open /dev/urandom
Warning: using system clock for seed instead (quality will be lower)

例えば,次のコードを ghci で実行すると全部同じ実数だったりするw

replicateM 10 (sample $ Uniform 0 1 :: IO Double)