2014-09-02 6 views
5

Sto scrivendo un programma che dovrebbe essere in grado di simulare molte istanze di provare il sistema di scommesse martingala con la roulette. Vorrei main prendere un argomento per dare il numero di test da eseguire, eseguire il test più volte e quindi stampare il numero di vittorie diviso per il numero totale di test. Il mio problema è che invece di finire con un elenco di Bool che potrei filtrare per contare i successi, ho un elenco di IO Bool e non capisco come posso filtrarlo.Come posso decomprimere una lista di lunghezza arbitraria di IO Bool

Ecco il codice sorgente:

-- file: Martingale.hs 
-- a program to simulate the martingale doubling system 

import System.Random (randomR, newStdGen, StdGen) 
import System.Environment (getArgs) 

red = [1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36] 

martingale :: IO StdGen -> IO Bool 
martingale ioGen = do 
    gen <- ioGen 
    return $ martingale' 1 0 gen 

martingale' :: Real a => a -> a -> StdGen -> Bool 
martingale' bet acc gen 
    | acc >= 5  = True 
    | acc <= -100 = False 
    | otherwise = do 
    let (randNumber, newGen) = randomR (0,37) gen :: (Int, StdGen) 
    if randNumber `elem` red 
     then martingale' 1 (acc + bet) newGen 
     else martingale' (bet * 2) (acc - bet) newGen 

main :: IO() 
main = do 
    args <- getArgs 
    let iters = read $ head args 
     gens = replicate iters newStdGen 
     results = map martingale gens 
     --results = map (<-) results 
    print "THIS IS A STUB" 

Come se avessi nelle mie osservazioni, ho praticamente voglio mappare (<-) sopra la mia lista di IO Bool, ma a quanto mi risulta, (<-) non è in realtà una funzione, ma un parola chiave. Qualsiasi aiuto sarebbe molto apprezzato.

+3

Si desidera ['sequenza'] (http://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Monad.html#v:sequence)' :: (Monad m) => [ma] -> m [a] ' – luqui

risposta

10

map martingale gens ti darà qualcosa tipo [IO Bool]. È quindi possibile utilizzare sequence a scompattarlo:

sequence :: Monad m => [m a] -> m [a] 

Un'alternativa più naturale è quella di utilizzare mapM direttamente:

mapM :: Monad m => (a -> m b) -> [a] -> m [b] 

esempio, si può scrivere

results <- mapM martingale gens 

Nota - anche dopo aver fatto lo in questo modo, il tuo codice sembra un po 'innaturale. Vedo alcuni vantaggi per la struttura, in particolare perché martingale' è una funzione pura. Comunque avere qualcosa di tipo IO StdGen -> IO Bool sembra un po 'strano.

riesco a vedere un paio di modi per migliorarlo:

  • make martingale' restituire un IO tipo stesso e spingere la chiamata newStdGen fino in fondo in esso
  • fanno gens uso replicateM piuttosto che replicate

Si consiglia di andare su http://codereview.stackexchange.com per un feedback più completo.

+0

Grazie mille! Non sapevo di questa funzione e non sapevo nemmeno che esistesse la visione del codice. – anthonybrice

+0

Dovresti dare un'occhiata alle funzioni in Control.Monad per avere un'idea di quali operazioni generiche sono disponibili su tipi monadici come 'IO': http://hackage.haskell.org/package/base-4.7.0.1/docs/Control -Monad.html –

Problemi correlati