2012-01-08 16 views

Odpowiedz

5

Standardowy System.Random ma czysty interfejs. Polecam owijając go w State g (niezależnie od używanego generatora), aby uniknąć wątkowania stanu; funkcja state sprawia funkcje toczenia jak next do stanowych działań proste:

next :: (RandomGen g) => g -> (Int, g) 
state :: (s -> (a, s)) -> State s a 
state next :: (RandomGen g) => State g Int 

Pakiet MonadRandom bazuje na interfejsie State g z pre-napisany owijarki do funkcji generatora; Myślę, że jest dość popularny.

Należy pamiętać, że nadal można uruchamiać akcje przy użyciu tego czystego interfejsu on the global RNG. MonadRandom ma evalRandIO do tego celu.

Myślę, że można napisać instancję (sierotę) RandomGen, aby użyć mwc-random z tymi.

+1

+1 dla 'MonadRandom', to jest droga. – luqui

+0

@hhird Co to jest tutaj wolne źródło losowości, które utrzyma go w czystości? ECC? –

+0

@JFritsch: Pamiętaj, że czyste nie oznacza tylko braku IO. Czysta funkcja musi zawsze zwracać ten sam wynik z tymi samymi argumentami. Jedynym "źródłem losowości" jest generator lub _seed_ ('g' w sygnaturach typu). – hammar

7

Podoba mi się pakiet mersenne-random-pure64. Na przykład można go używać tak, aby generować nieskończoną leniwy strumień losowych deblu z wartością początkową:

import Data.Word (Word64) 
import Data.List (unfoldr) 
import System.Random.Mersenne.Pure64 

randomStream :: (PureMT -> (a, PureMT)) -> PureMT -> [a] 
randomStream rndstep g = unfoldr (Just . rndstep) g 

toStream :: Word64 -> [Double] 
toStream seed = randomStream randomDouble $ pureMT seed 

main = print . take 10 $ toStream 42 

użyciu System.Random (randoms)

Można uzyskać podobny wynik z wbudowane randoms funkcji, które jest krótsze i bardziej ogólny (Dzięki ehird za wskazujące, że z):

import System.Random (randoms) 
import System.Random.Mersenne.Pure64 (pureMT) 

main = print . take 10 $ randomdoubles where 
    randomdoubles :: [Double] 
    randomdoubles = randoms $ pureMT 42 

czyni to wystąpienie MonadRandom

Po przeczytaniu około MonadRandom ciekawi mnie, jak uzyskać PureMT działającej jako jego przykład. Po wyjęciu z pudełka nie działa, ponieważ PureMT nie tworzy instancji RandomGen 's funkcji split. Jednym ze sposobów, aby to zadziałało, jest owinięcie PureMT w newtype i napisanie niestandardowej instancji split dla egzemplarza typu RandomGen, dla którego istnieje domyślna instancja MonadRandom.

import Control.Monad.Random 
import System.Random.Mersenne.Pure64 

getTenRandomDoubles :: Rand MyPureMT [Double] 
getTenRandomDoubles = getRandoms >>= return . take 10 

main = print $ evalRand getTenRandomDoubles g 
    where g = MyPureMT $ pureMT 42 


newtype MyPureMT = MyPureMT { unMyPureMT :: PureMT } 
myPureMT = MyPureMT . pureMT 

instance RandomGen MyPureMT where 
    next = nextMyPureMT 
    split = splitMyPureMT 

splitMyPureMT :: MyPureMT -> (MyPureMT, MyPureMT) 
splitMyPureMT (MyPureMT g) = (myPureMT s, myPureMT s') where 
    (s',g'') = randomWord64 g' 
    (s ,g') = randomWord64 g 

nextMyPureMT (MyPureMT g) = (s, MyPureMT g') where 
    (s, g') = randomInt g 
+2

Możesz to zrobić dla dowolnego 'RandomGen' (którego' PureMT' jest instancją), z 'randoms :: (RandomGen g, Random a) => g -> [a]'. – ehird

+0

@hh, och, nie wiedziałem o 'randach'! Zaktualizowałem moją odpowiedź –

+1

Istnieje również 'monad-mersenne-random' http://hackage.haskell.org/package/monad-mersenne-random zbudowany na bazie' mersenne-random-pure64'. Ma ładną właściwość, która pozwala na uruchamianie monadycznej iteracji w stałej pamięci (zobacz to pytanie: http://stackoverflow.com/questions/3236442/). – sastanin

2

Szczególnie ładne opakowanie z czystym interfejs, który nadaje się również do zastosowań kryptograficznych i jeszcze utrzymuje wysoką wydajność jest pakiet cprng-aes.

Udostępnia dwa interfejsy: czysty deterministyczny przy użyciu klas typów z System.Random oraz silny interfejs IO przy użyciu klas typów z pakietu Crypto-API.

Na marginesie: Generalnie wolałbym losowe pakiety mersenne nad mwc-random. Używają oryginalnego algorytmu Mersenne Twister iw moich testach porównują Mwc-random z dużym współczynnikiem.