问题
I am working on an Asteroid game made in Haskell with Graphics.gloss. Now I have defined a datatype for the asteroids like this:
data Asteroid = Asteroid { asteroidPos:: Point,
asteroidVel :: Vector,
asteroidSize :: Float }
So that it has a Position defined by a point, a velocity defined by a vector and it's size. Now I want to know how I could write an instance of Random for this datatype so that a new asteroid appears at a random time, on a random place with a random velocity. Does anyone know how I can accomplish this?
回答1:
There's already a Random
instance for Float
. Assuming that you also have Random
instances for Vector
and Point
, you can use them to define a Random
instance for Asteroid
:
instance Random Asteroid where
randomR (Asteroid pl vl sl, Asteroid ph vh sh) g =
let (p, g1) = randomR (pl, ph) g
(v, g2) = randomR (vl, vh) g1
(s, g3) = randomR (sl, sh) g2
in (Asteroid p v s, g3)
random g =
let (p, g1) = random g
(v, g2) = random g1
(s, g3) = random g2
in (Asteroid p v s, g3)
The randomR
function takes a range of values, from minimum (low) to maximum (high). How you define a meaningful range of a complex value like Asteroid
, I'll leave up to you; here, I'm simply assuming that you can pass a low and high Asteroid
value.
The first step uses the underlying Random
instance for Point
by calling randomR
. p
is a randomly generated Point
value, and g1
is the next random generator value to use.
Likewise, v
is a randomly generated Vector
value, generated by the underlying instance for Vector
.
Finally, s
is a Float
generated by randomR
for Float
.
The return value is a new Asteroid
value composed from p
, v
, and s
, plus the most recent generator g3
.
The implementation of random
follows the same template.
You could write this code in a prettier form, using e.g. using MonadRandom
, but for starters, I left the code in its raw form to show how it works.
来源:https://stackoverflow.com/questions/47133198/haskell-random-instance-of-own-datatype