wkoikingのブログ

内容は主にhaskellやxyzzy関連です。

【Haskell】 Stateモナドで乱数生成用モジュールを作る

今日もHaskellネタ。

Haskellでは避けて通れないモナドの話をしてみようと思ったのですが

・・・やっぱり難しい。

結局のところ、

モナドを理解する ≒ モナドインスタンスをたくさん覚える

だよなぁと思ったので、モナドについて解説するのはやめにして、 実際にモナドを使ったコードを書いてみます。

Stateモナドを使った、簡単な乱数ライブラリ

使い方

拡大

ソースコード

module EasyRandom (
  Random(..),
  random,
  uniform,
  permutation,
  normal,
  runRandom
) where

import Control.Monad.State.Lazy
 (state, State(..), runState)
import qualified System.Random as R
 (random, randomR, getStdRandom, StdGen(..), Random)
import qualified Data.Random.Normal as N
 (normal)

type Random a = State R.StdGen a

random :: Random Int
random = state R.random 

normal :: Random Double
normal = state N.normal

constant :: a -> Random a
constant = return

uniform :: R.Random a => (a, a) -> Random a
uniform (x,y) = state $ R.randomR (x,y)

permutation :: [a] -> Random [a]
permutation ls = permutation' (length ls) ls

permutation' :: Int -> [a] -> Random [a]
permutation' _  = return 
permutation' _ [x] = return [x]
permutation' n (x:xs) = do
  ys <- permutation' (n - 1) xs
  i <- uniform (0, n - 2)
  return (ys !! i) : update i x ys
 where
  update :: Int -> a -> [a] -> [a]
  update i x xs 
   | i < 0     = xs
   | otherwise = let (ls, (r:rs)) = splitAt i xs in ls ++ (x:rs)

runRandom :: Random a -> IO a
runRandom = R.getStdRandom . runState

以上です(汗)

おまけ