È possibile definire una funzione il cui tipo corrisponde a quello che si desidera avere, anche se più in generale.
import System.Random
randoms' :: (RandomGen g, Random a) => g -> Int -> ([a], g)
randoms' g n =
let (g1, g2) = split g
in (take n $ randoms g1, g2)
Anche se utilizza split
split :: g -> (g, g)
L'operazione split
permette di ottenere due distinti generatori di numeri casuali. Questo è molto utile nei programmi funzionali (ad esempio, quando si passa un generatore di numeri casuali alle chiamate ricorsive), ma è stato fatto pochissimo lavoro su implementazioni statisticamente valide di split
e hellip;
ancora non fa quello che vuoi. (Uso Bool
negli esempi di seguito facilitano il confronto visivo.)
ghci> g <- getStdGen
ghci> randoms' g 5 :: ([Bool], StdGen)
([False,False,False,True,False],1648254783 2147483398)
ghci> randoms' g 5 :: ([Bool], StdGen)
([False,False,False,True,False],1648254783 2147483398)
noti che le matrici casuali sono uguali.
Sebbene la funzione risolva il rischio di dividere il generatore, lo scartiamo prontamente. Invece, fanno uso di g2
infilando alla chiamata successiva come in
ghci> let (a1,g2) = randoms' g 5 :: ([Bool], StdGen)
ghci> let (a2,_) = randoms' g2 5 :: ([Bool], StdGen)
ghci> (a1,a2)
([False,False,False,True,False],[True,True,True,False,True]
Se il codice viene eseguito nel IO
Monade, è possibile utilizzare setStdGen
per sostituire il generatore globale di numeri casuali, alla fine, come in
myAction :: Int -> IO ([Float],[Float])
myAction n = do
g <- getStdGen
let (f1,g2) = randoms' g n
let (f2,g3) = randoms' g2 n
setStdGen g3
return (f1, f2)
Lo stato di threading è scomodo e soggetto a errori. Prendi in considerazione l'utilizzo di State
o ST
se disponi di un numero di piastre ripetuto.
Un'altra opzione è quella di ['split'] (http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:split) il generatore in due. Quindi puoi usare uno dei generatori risultanti per chiamare 'randoms' e continuare con l'altro. Questo funziona anche con liste infinite. – hammar