使用foldM生成随机数列表
我想生成一个随机数列表,其中每个随机数的范围由提供的列表的元素确定。我以为我有一些有意义的东西,但我收到了我不明白的错误:(
这就是我所拥有的:
useRNG nums min = do
generator <- get
let (val, generator') = randomR (min, 51) generator
put generator'
return $ val : nums
foldM useRNG [] [0 .. 50]
任何人都可以帮助我吗?
I want to generate a list of random numbers, where the range of each random number is determined by elements of a provided list. I thought I had something that made sense, but I get errors I don't understand :(
Here's what I have:
useRNG nums min = do
generator <- get
let (val, generator') = randomR (min, 51) generator
put generator'
return $ val : nums
foldM useRNG [] [0 .. 50]
Can anyone help me out?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是
useRNG
可以生成各种类型的数字(Random
的任何实例),并且可以在各种类型的 monad 中工作(状态为Random
实例的任何状态 monad) code>RandomGen),从其推断的类型签名可以看出:...但是当您使用它时,您还没有指定您真正想要的哪种具体类型。
如果您使用类型签名来消除歧义:
那么它就可以正常工作。您还可以通过在
useRNG
上放置类型签名来实现此目的:现在,您可能会想:如果
useRNG
可以很好地处理所有这些类型,为什么不能也测试一下吗?答案是单态限制,这是相当晦涩难懂的- 受到许多 Haskell 用户的喜欢。您可以通过将其放在
文件顶部或给
test
一个显式类型签名来避免这种情况:您可以使用 GHCi 找出正确的类型签名:(
我在检查之前编写了显式类型签名GHCi,这就是为什么我的略有不同。)
但是,这种类型签名对于实际用途来说有点太多多态性 - 你基本上会推迟歧义,直到你实际使用结果 - 所以我建议更具体地指定它在这种情况下。例如,您可以保持随机数类型的
test
通用性,而无需对状态单子和生成器类型进行不必要的多态性:您可能还需要考虑使用 MonadRandom,它将所有标准随机数生成工具包装在基于状态 monad 的接口中,因此您不必:)
The problem is that
useRNG
can generate all kinds of numbers (any instance ofRandom
), and work in all kinds of monads (any state monad whose state is an instance ofRandomGen
), as can be seen from its inferred type signature:...but when you use it, you haven't specified which concrete types you actually want.
If you disambiguate with a type signature:
then it works fine. You could also accomplish this by putting a type signature on
useRNG
:Now, you might be thinking: if
useRNG
works fine with all these types, why can'ttest
too? The answer is the monomorphism restriction, which is fairly arcane and not well-liked by many Haskell users. You can avoid it by either puttingat the top of your file, or giving
test
an explicit type signature:You can find out the correct type signature with GHCi:
(I wrote the explicit type signature before checking with GHCi, which is why mine is slightly different.)
However, this type signature is a little too polymorphic for practical uses — you'll basically be putting the ambiguity off until you actually use the result — so I'd suggest specifying it more concretely in this instance. You could, for instance, keep
test
generic over the type of random number without the needless polymorphism over the state monad and generator type:You might also want to consider using MonadRandom, which wraps all the standard random number generation facilities in a state monad-based interface so you don't have to :)