简体   繁体   中英

Generating random numbers in Haskell

I'm reading chapter 9 ( More Input and More Output ) of Learn You a Haskell for Great Good . Now I'm about to learn how to generate random numbers in Haskell (it's so exciting!). Here is a citation from the book:

To manually make a random generator, use the mkStdGenfunction . It has a type of mkStdGen :: Int -> StdGen . It takes an integer, and based on that, gives us a random generator. Okay then, let's try using random and mkStdGenin tandem to get a (hardly) random number.

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)

What's this? Ah, right, the random function can return a value of any type that's part of the Random type class, so we need to inform Haskell which type we want. Also let's not forget that it returns a random value and a random generator in a pair.

The problem is that I don't get this error, in fact, I can do the following:

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

So my question is why can I evaluate this expression without getting the exception?

I would wager a guess and say that the defaulting rules for GHCI have been extended since LYAH was written. This means that in cases where a type is ambiguous, GHCI tries to select a specific type. In this case it looks like random (mkStdGen 100) defaults to (Integer, StdGen) .

If on the other hand I make a file test.hs

import System.Random

foo = random (mkStdGen 100)

... and try to load it in GHCI, I get:

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.

If I wanted the same result, I would have to fix the type of foo , like so:

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

For more information on Extended Defaulting, see section 2.4.8 in the GHC docs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM