data Move = Rock | Paper | Scissors deriving (Eq, Show)
data Strategy = S Move (Move -> Strategy)

play s1 s2 0 = (0,0)
play (S m1 s1') (S m2 s2') n = let (n1,n2) = play (s1' m2) (s2' m1) (n-1)
                               in case (m1,m2) of
                                  (Rock    , Scissors) -> (n1+1, n2)
                                  (Scissors, Paper   ) -> (n1+1, n2)
                                  (Paper   , Rock    ) -> (n1+1, n2)
                                  (Scissors, Rock    ) -> (n1, n2+1)
                                  (Paper   , Scissors) -> (n1, n2+1)
                                  (Rock    , Paper   ) -> (n1, n2+1)
                                  _                    -> (n1, n2)

pureRock = S Rock (const pureRock)
pureRockPaper = S Rock (const purePaperRock)
purePaperRock = S Paper (const pureRockPaper)
pureCopy m = S m pureCopy
