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
相关产品推荐
相关产品推荐

