Me gusta el paquete mersenne-random-pure64. Por ejemplo, puede utilizar de esta manera para generar una corriente perezosa infinita de dobles aleatorios a partir de un valor de semilla:
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
usando System.Random (randoms)
Usted puede obtener una salida similar a la incorporado randoms
función, que es más corto y más general (Gracias a ehird por señalarlo):
import System.Random (randoms)
import System.Random.Mersenne.Pure64 (pureMT)
main = print . take 10 $ randomdoubles where
randomdoubles :: [Double]
randomdoubles = randoms $ pureMT 42
por lo que es una instancia de MonadRandom
Después de leer aproximadamente MonadRandom
tengo curiosidad por cómo obtener PureMT
trabajando como ejemplo de ello. Fuera de la caja no funciona, porque PureMT
no crea la instancia RandomGen
de la función split
. Una forma de hacerlo funcionar es ajustar PureMT
en un newtype
y escribir una instancia personalizada split
para la clase de tipo RandomGen
, para la cual existe una instancia predeterminada 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
+1 para 'MonadRandom', es el camino a seguir. – luqui
@ehird ¿Cuál es aquí la fuente libre de IO de aleatoriedad que lo mantendría puro? ECC? –
@JFritsch: Recuerde, pure no solo significa no IO. Una función pura debe _siempre_ devolver el mismo resultado dados los mismos argumentos. La única "fuente de aleatoriedad" es el generador o _seed_ ('g' en las firmas de tipo). – hammar