2014-09-29 211 views
4

我在阅读第9章(更多输入和更多输出)的了解您对Haskell的好好处。现在我要学习如何在Haskell中生成随机数字(这太令人兴奋了!)。以下是本书中的一段引文:在Haskell中生成随机数

要手动生成随机生成器,请使用mkStdGenfunction。它有一个mkStdGen :: Int -> StdGen的类型。它需要一个整数,并基于此,给我们一个随机生成器。好吧,我们尝试使用randommkStdGenin串联来获得(几乎)随机数。

ghci> random (mkStdGen 100) 
<interactive>:1:0: 
Ambiguous type variable `a' in the constraint: 
`Random a' arising from a use of `random' at <interactive>:1:0-20 
Probable fix: add a type signature that fixes these type variable(s) 

这是什么?啊,对,random函数可以返回任何类型的值,这是Random类型类的一部分,所以我们需要通知Haskell我们想要的类型。另外我们不要忘记它会返回一个随机值和一对随机生成器。

的问题是,我没有得到这个错误,其实,我可以做到以下几点:

*Main> :m + System.Random 
*Main System.Random> random (mkStdGen 100) 
(-3633736515773289454,693699796 2103410263) 

所以我的问题是,为什么我不能评价没有得到外,这个体现在哪里?

+0

只是对未来的一个简短提示:如果你真的想在Haskell中使用随机数,mwc-random包会更快并且会产生更高质量的随机数。 – tibbe 2014-09-30 11:42:53

回答

10

我敢打赌,说自从LYAH写出以来,GHCI的违约规则已经延长了。这意味着,在类型不明确的情况下,GHCI会尝试选择特定的类型。在这种情况下,它看起来像random (mkStdGen 100)默认为(Integer, StdGen)

如果在另一方面,我做一个文件test.hs

import System.Random 

foo = random (mkStdGen 100) 

...,并尝试将其加载到GHCI,我得到:

test.hs:3:7: 
    No instance for (Random a0) arising from a use of ‘random’ 
    The type variable ‘a0’ is ambiguous 
    Relevant bindings include 
     foo :: (a0, StdGen) (bound at test.hs:3:1) 
    Note: there are several potential instances: 
     instance Random Bool -- Defined in ‘System.Random’ 
     instance Random Foreign.C.Types.CChar -- Defined in ‘System.Random’ 
     instance Random Foreign.C.Types.CDouble 
     -- Defined in ‘System.Random’ 
     ...plus 33 others 
    In the expression: random (mkStdGen 100) 
    In an equation for ‘foo’: foo = random (mkStdGen 100) 
Failed, modules loaded: none. 

如果我想同样的结果,我将不得不解决的foo类型,就像这样:

foo :: (Integer, StdGen) 
foo = random (mkStdGen 100) 

有关扩展违约的更多信息,请参阅section 2.4.8 in the GHC docs

+0

我认为有一点微妙之处在于:随机'方法可以根据类型自由修改发生器。如果生成器生成“Int”值,并且您有一个使用结果的“intToRandom”方法,那么使用它生成多态随机数就没有问题了。但是它有很好的理由,特别是不同类型需要不同数量的随机性。 – dfeuer 2014-09-29 13:34:30

+0

我敢打赌,这是最近GHCi用Show实例推断类型以显示结果的方式。 'let r = random $ mkStdGen 100'只有当显示被传递给'Int'或'Integer'实例时,随机值随机值的多态类型才会与'Random'约束'r :: Random a =>(a,StdGen) – 2014-09-29 13:45:00

+1

附注:您可以在GHCi中用':set -XNoExtendedDefaultRules'关闭扩展默认规则。设置此标志后,会发生错误(尽管该消息与LYAH中的消息不同)。 – bheklilr 2014-09-29 16:22:35