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 ofmkStdGen :: Int -> StdGen
. It takes an integer, and based on that, gives us a random generator. Okay then, let’s try usingrandom
andmkStdGenin
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 theRandom
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?
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 .
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With