First attempt at writing Rock Paper Scissors game 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 -&gt; Throw -&gt; Bool
Rock     `beats` Scissors = True
Paper    `beats` Rock     = True
Scissors `beats` Paper    = True
_        `beats` _        = False

play :: Throw -&gt; Throw -&gt; 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 &lt;- getLine &gt;&gt;= readIO
  p2 &lt;- liftM (fst . random) getStdGen
  putStrLn $ show p1 ++ " vs. " ++ show p2
  putStrLn $ play p1 p2
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.