Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating random numbers in Haskell

Tags:

random

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?

like image 264
Mark Karpov Avatar asked Sep 29 '14 13:09

Mark Karpov


People also ask

What is StdGen in Haskell?

StdGen , the standard pseudo-random number generator provided in this library, is an instance of RandomGen . It uses the SplitMix implementation provided by the splitmix package. Programmers may, of course, supply their own instances of RandomGen .


Video Answer


1 Answers

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

like image 102
Sarah Avatar answered Oct 19 '22 21:10

Sarah