user2999349
user2999349

Reputation: 879

Haskell random generator : chain generation of random values

I need to generate 3 random values in a row, where the first one determines whether the last 2 ones will be calculated or not:

randomEnemy :: World -> World
randomEnemy world@(World{enemies=e, rndGen}) = doR0 (randomR (0, 10) rndGen)
    where
        doR0 (a, g) =
            if a <= 1
                then doR1 (randomR (-562, 562) g)
                else world
        doR1 (a, g) = doR2 (a, randomR (-288, 288) g)
        doR2 (a, (b, g))  = world { enemies = e ++ [Enemy (a,b) (0,0)],
                                    rndGen=g }

However this is not working and I do not know why. It should simply calculate a random value between 0 and 10 which determines whether or not a random enemy should be spawned, then if so it should calculate 2 more random numbers for the position, otherwise return the current game state unchanged.

Although if I change the first call to doR0 to doR1 it DOES work, which leaves me totally clueless..

If anyone could help me out on this it'd be much appreciated!

Best regards, Skyfe.

EDIT: The errors it throws (sumarized):

No instance for (Ord a0) arising from a use of `DoR0`
The type variable `a0 is ambigious`
...
No instance for (Random a0) arising from a use of `RandomR`
The type variable `a0` is ambigious

Upvotes: 1

Views: 190

Answers (1)

bheklilr
bheklilr

Reputation: 54078

Your problem comes from GHC not being able to figure out what type randomR (0, 10) rndGen should return. The only constraints you've placed on this value is that you need to be able to compare it to 1, so it needs to satisfy the Random, Num and Ord typeclasses. The other doRN work because the random values you're generating are being placed into a data structure that has concrete types specified, so the compiler can infer what type of value to return from the other uses of randomR. You can fix this by specifying that it needs to return an Int in several places, the cleanest is by adding a type signature to doR0 of (Int, StdGen) -> World, so now the compiler can infer that randomR (0, 10) rndGen returns a value of type (Int, StdGen) since it's consumed by doR0.

Upvotes: 2

Related Questions