我正在编写一个程序,应该可以模拟许多用轮盘赌尝试鞅投注系统的实例.我想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"
Run Code Online (Sandbox Code Playgroud)
就像我在评论中一样,我基本上想要映射(<-)我的列表IO Bool,但据我所知,它(<-)实际上不是一个函数而是一个关键字.任何帮助将不胜感激.
GS *_*ica 10
map martingale gens会给你一些类型的东西[IO Bool].然后您可以使用sequence它来解压缩它:
sequence :: Monad m => [m a] -> m [a]
Run Code Online (Sandbox Code Playgroud)
更自然的替代方案是mapM直接使用:
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
Run Code Online (Sandbox Code Playgroud)
即你可以写
results <- mapM martingale gens
Run Code Online (Sandbox Code Playgroud)
注意 - 即使这样做,您的代码也会感觉有点不自然.我可以看到结构的一些优点,特别是因为它martingale'是一个纯函数.但是有一些类型IO StdGen -> IO Bool似乎有点奇怪.
我可以看到几种方法来改进它:
martingale'返回一个IO类型并将newStdGen调用一直推入其中gens利用replicateM而不是replicate您可能需要访问http://codereview.stackexchange.com以获得更全面的反馈.