【问题标题】:How can I unpack an arbitrary length list of IO Bool如何解压任意长度的 IO Bool 列表
【发布时间】:2014-09-02 05:37:32
【问题描述】:

我正在编写一个程序,它应该能够模拟许多尝试使用轮盘赌的鞅投注系统的实例。我希望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"

就像我在我的 cmets 中一样,我基本上想将 (&lt;-) 映射到我的 IO Bool 列表上,但据我了解,(&lt;-) 实际上不是一个函数,而是一个关键字。任何帮助将不胜感激。

【问题讨论】:

  • 你想要sequence:: (Monad m) =&gt; [m a] -&gt; m [a]

标签: haskell io


【解决方案1】:

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 -&gt; IO Bool 类型的东西似乎有点奇怪。

我可以看到几种改进方法:

  • 使martingale' 自身返回一个IO 类型并将newStdGen 调用一直向下推入其中
  • 使gens 使用replicateM 而不是replicate

您可能需要前往http://codereview.stackexchange.com 以获得更全面的反馈。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2023-03-04
  • 2013-10-06
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
  • 2022-01-15
  • 2012-01-17
  • 1970-01-01
相关资源
最近更新 更多