2014-09-02 19 views
5

我正在編寫一個應該能夠模擬許多使用輪盤賭嘗試鞅投注系統的實例的程序。我希望main能夠給出一個參數,給出要執行的測試次數,多次執行測試,然後打印勝利次數除以總測試次數。我的問題是,而不是結束與Bool列表,我可以過濾以計數成功,我有一個IO Bool列表,我不明白我可以如何過濾。如何解開任意長度的IO列表Bool

這裏的源代碼:

-- 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" 

就像我在我的意見,我基本上是想通過我的IO Bool列表地圖(<-),但據我所知,(<-)實際上不是一個功能,而是一個關鍵詞。任何幫助將不勝感激。

+3

你想要['sequence'](http://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Monad.html#v:sequence)'::(Monad m)=> [ma] - > m [a]' – luqui 2014-09-02 05:40:38

回答

10

map martingale gens會給你一些[IO Bool]類型的東西。然後,您可以使用sequence把它解壓到:

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

一種更自然的選擇是直接使用mapM

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

比如,你可以寫

results <- mapM martingale gens 

注 - 即使這件事以後這樣,你的代碼感覺有點不自然。我可以看到結構的一些優點,特別是因爲martingale'是一個純函數。然而有IO StdGen -> IO Bool類型的東西似乎有點奇怪。

我可以看到一對夫婦的改進辦法:

  • 化妝martingale'返回IO類型本身和向下推動newStdGen呼叫一路進去
  • 使gens使用replicateM而非replicate

您可能想要轉到http://codereview.stackexchange.com以獲得更全面的反饋。

+0

非常感謝!我不知道這個函數,也不知道codereview是否存在。 – anthonybrice 2014-09-02 05:55:36

+0

您應該查看Control.Monad中的函數,以瞭解可以在像IO這樣的單類類型上使用哪些通用操作:http://hackage.haskell.org/package/base-4.7.0.1/docs/Control -Monad.html – 2014-09-02 06:02:25