Skip to content

Instantly share code, notes, and snippets.

@KGZM
Last active August 29, 2015 14:11
Show Gist options
  • Save KGZM/82e440d5284fc20942f0 to your computer and use it in GitHub Desktop.
Save KGZM/82e440d5284fc20942f0 to your computer and use it in GitHub Desktop.
Simple Comparison Between Haskell and OCaml
{- rps.hs Simple Rock Paper Scissors written in Haskell
- for translation to Ocaml as a learning exercise.
-}
data Move = Rock | Paper | Scissors deriving (Show, Eq)
data Player = Player String deriving (Show, Eq)
data Outcome = Winner Player | Tie deriving (Show, Eq)
name :: Player -> String
name (Player s) = s
beats :: Move -> Move -> Bool
beats Rock Scissors = True
beats Scissors Paper = True
beats Paper Rock = True
beats _ _ = False
victor :: (Player, Move) -> (Player, Move) -> Outcome
victor (p1, m1) (p2, m2)
| m1 `beats` m2 = Winner p1
| m2 `beats` m1 = Winner p2
| otherwise = Tie
play :: Player -> Move -> Player -> Move -> String
play p1 m1 p2 m2 =
case victor (p1, m1) (p2, m2) of
Tie -> (name p1) ++ " and " ++ (name p2) ++ " tie with " ++ (show m1) ++ "."
Winner w ->
let (wp, wm, lp,lm) =
if w == p1
then (p1, m1, p2, m2)
else (p2, m2, p1, m1)
in (name wp) ++ "'s " ++ (show wm) ++ " defeats " ++ (name lp) ++ "'s " ++ (show lm) ++ "."
jimmy = Player "Jimmy"
jack = Player "Jack"
moves = [Rock, Paper, Scissors]
main = do
let season = do m1s <- moves
m2s <- moves
return $ play jimmy m1s jack m2s
mapM_ putStrLn season
(* rps.ml : Translation of Rock Paper Scissors from
* Haskell to Ocaml as a learning exercise.
*)
type move = Rock | Paper | Scissors
type player = Player of string
type outcome = Winner of player | Tie
let name (Player s) = s
let moveName m = match m with
| Rock -> "rock"
| Paper -> "paper"
| Scissors -> "scissors"
let beats m1 m2 = match m1, m2 with
| Rock, Scissors -> true
| Scissors, Paper -> true
| Paper, Rock -> true
| _, _ -> false
let victor (p1, m1) (p2, m2) = match () with
| () when beats m1 m2 -> Winner p1
| () when beats m2 m1 -> Winner p2
| _ -> Tie
let play p1 m1 p2 m2 =
let winstring = Printf.sprintf "%s's %s defeats %s's %s."
and tiestring = Printf.sprintf "%s and %s tie with %s."
in
match victor (p1, m1) (p2, m2) with
| Tie -> tiestring (name p1) (name p2) (moveName m1)
| Winner w ->
let wp, wm, lp, lm =
if w = p1
then p1, m1, p2, m2
else p2, m2, p1, m1
in winstring (name wp) (moveName wm) (name lp) (moveName lm)
let jimmy = Player "Jimmy"
let jack = Player "Jack"
let moves = [Rock; Paper; Scissors]
let main () =
let concatMap f l = List.fold_right (fun v a -> (f v) @ a) l []
and (|>) v f = f v in
let season = moves |> concatMap (fun m1 ->
moves |> List.map (fun m2 -> play jimmy m1 jack m2)
)
in List.iter print_endline season
let _ = main ()
# rps.coffee : CoffeeScript version of Rock Paper Scissors
# for comparison with Haskell and OCaml versions.
move = {
rock: "scissors"
scissors: "paper"
paper: "rock"
}
player = (name) -> {name}
outcome = (winner) -> {
type: if winner then "winner" else "tie"
winner: winner
}
beats = (m1, m2) -> move[m1] == m2
victor = (p1, m1, p2, m2) ->
switch
when beats m1, m2 then outcome(p1)
when beats m2, m1 then outcome(p2)
else outcome() #This is our tie, not very snazzy.
play = (p1, m1, p2, m2) ->
result = victor p1, m1, p2, m2
if not result.winner
"#{p1.name} and #{p2.name} tie with #{m1}."
else
[wp, wm, lp, lm] =
if result.winner is p1
[p1, m1, p2, m2]
else
[p2, m2, p1, m1]
"#{wp.name}'s #{wm} defeats #{lp.name}'s #{lm}."
jimmy = player "jimmy"
jack = player "jack"
moves = ["rock", "paper", "scissors"]
moves.reduce((acc, m1) ->
acc.concat moves.map (m2) ->
play jimmy, m1, jack, m2
,[]).forEach((s) -> console.log s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment