我正在编写一个程序,应该能够模拟使用轮盘赌尝试鞅投注系统的许多实例。我希望main
接受一个参数,给出要执行的测试次数,多次执行测试,然后打印获胜次数除以测试总次数。我的问题是,我有一个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"
的列表,我不明白我如何过滤它。< / p>
这是源代码:
(<-)
就像我在评论中所说的那样,我基本上希望将IO Bool
映射到我的(<-)
列表中,但据我了解,{{1}}实际上并不是一个函数,而是一个关键字。任何帮助将不胜感激。
答案 0 :(得分: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以获得更全面的反馈。