Haskell IO 动作中的递归

Haskell recursion in IO action

还是一个初学者,无法理解 IO 动作中的递归循环。假设:

fMinInspect :: Int
fMinInspect = 1
fMaxInspect :: Int
fMaxInspect = 12
-- fNoInspectPerHour :: IO ()
fNoInspectPerHour = do
  generateInspect <- randomRIO (fMinInspect,fMaxInspect)
  putStrLn ""

我想生成一个列表,比方说我要随机检查的 10 台机器,然后我可以重复调用将 10x fNoInspectPerHour 添加到列表中的东西吗?

我尝试了一个外部函数,但我无法从 IO () 中获取操作。请注意 putStrLn 只是终止 do 块,因为我不需要控制台输出。

PS。关于在没有 putStrLn 的情况下终止 do 块的建议也欢迎。

randomIO (fMinInspect, fMaxInspect)是一个IO动作,一个(Num a, Random a) => IO a类型的值。 (为简单起见,我们假设 a 从现在开始就是 Int。) 请注意,每次执行动作都会产生一个不同的随机值;这就是 IO Int 作为生成随机值的 动作 和本身就是随机值之间的区别。

一旦我们有了那个动作,我们就可以用 replicate 10 (randomRIO (fMinInspect, fMaxInspect)) 创建一个动作列表;这将具有类型 [IO Int],IO 操作的 10 个副本。

sequence 函数可以将您的 IO 操作列表更改为生成值列表的 IO 操作(每个值由相应的操作生成),转换类型为 [IO Int] 的值转换为 IO [Int].

类型的值
> fMinInspect = 1
> fMaxInspect = 12
> sequence (replicate 10 (randomRIO (fMinInspect, fMaxInspect)))
[1,6,6,1,7,5,8,4,7,7]

(这里,和往常一样,GCHi 正在执行由 sequence 生成的 IO 操作,并且 returns 由该 IO 操作生成的结果。)

如果你真的想在这里自己使用递归,你可以这样写

fNoInspectPerHour :: Int -> IO () 
fNoInspectPerHour 0 = return () 
fNoInspectPerHour n = do { 
    generateInspect <- randomRIO (fMinInspect,fMaxInspect) ; 
    --  Int            IO Int
    putStrLn generateInspect ;    -- or do some other IO action
    --                 IO ()
    fNoInspectPerHour (n-1) 
    --                 IO ()
    }