Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I made this Rock Paper Scissors game and I would like for this to be critiqued.

import System.IO
import System.Random
import Control.Monad
import Control.Arrow

data Throw = Rock | Paper | Scissors
           deriving (Show, Read, Enum, Bounded)

instance Random Throw where
  random g = first toEnum $ randomR (a, b) g
    where a = fromEnum (minBound :: Throw)
          b = fromEnum (maxBound :: Throw)

  randomR (a, b) g = first toEnum $ randomR (a', b') g
    where a' = fromEnum a
          b' = fromEnum b

beats :: Throw -> Throw -> Bool
Rock     `beats` Scissors = True
Paper    `beats` Rock     = True
Scissors `beats` Paper    = True
_        `beats` _        = False

play :: Throw -> Throw -> String
play p1 p2
  | p1 `beats` p2 = "You win!"
  | p2 `beats` p1 = "You lose."
  | otherwise     = "Tie."

main :: IO ()
main = do
  putStr "Enter your move [Rock, Paper, or Scissors]: "
  hFlush stdout
  p1 <- getLine >>= readIO
  p2 <- liftM (fst . random) getStdGen
  putStrLn $ show p1 ++ " vs. " ++ show p2
  putStrLn $ play p1 p2
share|improve this question
I can't see any way to improve. Well done! Hackage should have a template Haskell library to derive of Random instances but as far as I know it doesn't have yet. – nponeccop Nov 10 '12 at 9:06
up vote 3 down vote accepted

The style is pretty good, I can just see two minor improvements you could do: Firstly, you can define random in terms of your own randomR in order to save a few keystrokes:

instance Random Throw where
  random = randomR (minBound, maxBound)
  randomR (a, b) g = ...

At this point Haskell's typing even derives the type of minBound for you, so you can lose the explicit annotations.

Second, you should probably use randomIO instead of liftM (fst . random) getStdGen. That is not only shorter, but also updates the generator state, which means that you won't get the same result if you call it twice in the program.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.