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

Haskell随机数生成函数的参数化边界问题求解

为Haskell随机数生成函数参数化边界的正确方法

你遇到的两个错误都源于参数传递和类型签名的问题,以下是具体修正方案:

错误原因分析

  1. 递归调用参数缺失:修改后的函数签名需要4个参数(数量、起始值、结束值、生成器),但你在递归调用时只传了(n-1)和newGen,少了start和end,导致函数返回的是未完全应用的函数,而非预期的元组([a], g),因此无法匹配(restOfList, finalGen)模式。
  2. 类型签名不匹配:你将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:46:32