You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell猜数字游戏运行异常 getStdGen相关问题排查

Haskell猜数字游戏随机数生成异常问题

以下代码本应实现一个简单的猜数字游戏:

import           Control.Monad (unless)
import           System.Random (Random (randomR), StdGen, getStdGen)

main :: IO ()
main = do
  gen <- getStdGen
  askForANumber gen

askForANumber :: StdGen -> IO ()
askForANumber gen = do
  let (randNumber, gen) = randomR (1, 10) gen :: (Int, StdGen)
  putStrLn "La ce numar intre 1 si 10 ma gandesc?"
  numberString <- getLine

  unless (null numberString) $ do
    let number = read numberString

    if randNumber == number
      then putStrLn "Ai ghicit!"
      else putStrLn $ "Imi pare rau era " ++ show randNumber

    askForANumber gen

我是Haskell初学者,程序运行结果和预期不符:
运行结果截图
如果我将第7行代码替换为:

askForANumber (mkStdGen 42)

程序即可正常运行,因此我推测问题与getStdGen有关,想知道自己存在哪些理解或编写错误。


问题原因

问题出在以下代码行:

let (randNumber, gen) = randomR (1, 10) gen :: (Int, StdGen)

此处出现了gen变量的递归引用问题:let绑定左侧新定义的gen变量,遮蔽了函数参数传入的同名gen,导致randomR调用时引用的是当前正在定义、未完成求值的gen,而非外部传入的随机数生成器,最终随机数生成逻辑异常。

修复方法

将问题行替换为:

let (randNumber, newGen) = randomR (1, 10) gen :: (Int, StdGen)

避免同名变量遮蔽导致的递归引用,后续递归调用askForANumber时传入新生成的newGen,程序即可按预期正常运行。


内容的提问来源于stack exchange,提问作者Calin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:24:30