Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a random value from a user-defined data type in Haskell

Similar: Haskell Random from Datatype

I have created a data type to contain the different weapons in the Rock Paper Scissor game.

data Weapon = Rock | Paper | Scissor

Now I would like to generate a random weapon which will be used by the computer against the user. I have take a look at the similar link I posted at the beginning but It seems too general for me.

I am able to generate random numbers from any other type. What I can get my head around is how to make my data type an instance of the Random class.

like image 216
Oni Avatar asked Aug 04 '12 19:08

Oni


1 Answers

To generate a random Weapon, whether you make Weapon an instance of Random or not, what you need is a way to map numbers to Weapons. If you derive Enum for the type, a map to and from Ints is defined by the compiler. So you could define

randomWeapon :: RandomGen g => g -> (Weapon, g)
randomWeapon g = case randomR (0,2) g of
                   (r, g') -> (toEnum r, g')

for example. With an Enum instance, you can also easily make Weapon an instance of Random:

instance Random Weapon where
    random g = case randomR (0,2) g of
                 (r, g') -> (toEnum r, g')
    randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
                        (r, g') -> (toEnum r, g')

If there is a possibility of adding or removing constructors from the type, the best way to keep the bounds for randomR in sync with the type is to also derive Bounded, as Joachim Breitner immediately suggested:

data Weapon
    = Rock
    | Paper
    | Scissors
      deriving (Bounded, Enum)

instance Random Weapon where
    random g = case randomR (fromEnum (minBound :: Weapon), fromEnum (maxBound :: Weapon)) g of
                 (r, g') -> (toEnum r, g')
    randomR (a,b) g = case randomR (fromEnum a, fromEnum b) g of
                        (r, g') -> (toEnum r, g')
like image 111
Daniel Fischer Avatar answered Oct 23 '22 06:10

Daniel Fischer