Haskell随机数生成函数的参数化边界问题求解
为Haskell随机数生成函数参数化边界的正确方法
你遇到的两个错误都源于参数传递和类型签名的问题,以下是具体修正方案:
错误原因分析
- 递归调用参数缺失:修改后的函数签名需要4个参数(数量、起始值、结束值、生成器),但你在递归调用时只传了
(n-1)和newGen,少了start和end,导致函数返回的是未完全应用的函数,而非预期的元组([a], g),因此无法匹配(restOfList, finalGen)模式。 - 类型签名不匹配:你将
start和end的类型设为n(即数量的类型),但randomR要求边界类型与生成的随机数类型a一致,这导致生成的value类型为n,无法加入类型为[a]的列表中。
修正后的代码
import System.Random finiteRandoms :: (Eq n, Num n, RandomGen g, Random a) => n -> a -> a -> g -> ([a], g) finiteRandoms 0 _ _ g = ([], g) finiteRandoms n start end g = let (value, newGen) = randomR (start, end) g (restOfList, finalGen) = finiteRandoms (n-1) start end newGen in (value : restOfList, finalGen)
关键修改点
- 修正类型签名:将
start和end的类型从n改为a,确保与randomR的边界类型要求一致;同时移除了不必要的Num a约束(Random类型类已涵盖可生成随机数的数值/非数值类型,若仅需数值随机数可保留该约束)。 - 补全递归参数:递归调用时传递
start和end参数,保证函数签名匹配,返回正确的元组结果。 - 基准情况优化:用下划线
_忽略start和end参数,明确表示这两个参数在基准情况中无意义。
测试示例
在GHCi中运行以下命令:
finiteRandoms 3 10 50 (mkStdGen 3)
会得到类似如下的结果(生成器状态可能略有不同):
([31,13,42],StdGen {unStdGen = SMGen 9186733390819170434 2092789425003139053})
内容的提问来源于stack exchange,提问作者Yago
相关产品推荐
相关产品推荐

