lundi 6 janvier 2020

Generate a random list of custom data type, where values provided to data constructor are somehow bounded within a range

I have defined a Point data type, with a single value constructor like so:

data Point = Point {
  x :: Int,
  y :: Int,
  color :: Color
} deriving (Show, Eq)

data Color = None
  | Black
  | Red
  | Green
  | Blue
  deriving (Show, Eq, Enum, Bounded)

I have found an example of making a Bounded Enum an instance of the Random class and have made Color an instance of it like so:

instance Random Color where
  random g = case randomR (1, 4) g of
    (r, g') -> (toEnum r, g')
  randomR (a, b) g = case randomR (fromEnum a, fromEnum b) g of
    (r, g') -> (toEnum r, g')

I was then able to find out how to make Point an instance of the Random class also:

instance Random Point where
  randomR (Point xl yl cl, Point xr yr cr) g =
    let (x, g1) = randomR (xl, xr) g
        (y, g2) = randomR (yl, yr) g1
        (c, g3) = randomR (cl, cr) g2
    in (Point x y c, g3)
  random g =
    let (x, g1) = random g
        (y, g2) = random g1
        (c, g3) = random g2
    in (Point x y c, g3)

So, this let's me make random point values. But, what I'd like to do is be able to create a list of random Point values, where the x and the y properties are bounded within some range whilst leaving the color property to be an unbounded random value. Is this possible with the way I am currently modelling the code, or do I need to rethink how I construct Point values? For instance, instead of making Point an instance of the Random class, should I just create a random list of Int in the IO monad and then have a pure function that creates n Points, using values from the random list to construct each Point value?




Aucun commentaire:

Enregistrer un commentaire