如何解压缩任意长度的IO Bool列表

时间:2014-09-02 05:37:32

标签: haskell io

我正在编写一个程序,应该能够模拟使用轮盘赌尝试鞅投注系统的许多实例。我希望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}}实际上并不是一个函数,而是一个关键字。任何帮助将不胜感激。

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以获得更全面的反馈。