I'm making my way through some introductory material on Haskell and trying to complete this silly Rock, Paper, Scissors implementation for the command line.
I would think that a type guard on the input would be good enough to convince the compiler that the input is of the type RPS
, but alas, it is not.
How does one go about telling the compiler that input data is of one type or another?
data RPS = Rock | Paper | Scissors
_shoot :: RPS -> RPS -> String
_shoot Rock Paper = "Paper beats rock, you win!"
_shoot Paper Rock = "Paper beats rock, you loose."
_shoot Rock Scissors = "Rock beats scissors, you loose."
_shoot Scissors Rock = "Rock beats scissors, you win!"
_shoot Paper Scissors = "Scissors beats paper, you win!"
_shoot Scissors Paper = "Scissors beats paper, you loose!"
_shoot Rock Rock = "Tie!"
_shoot Scissors Scissors = "Tie!"
_shoot Paper Paper = "Tie!"
isRPS :: String -> Bool
isRPS s = elem s ["Rock", "Paper", "Scissors"]
main :: IO ()
main = do
putStrLn "Rock, Paper, or Scissors?"
choice <- getLine
if isRPS choice -- this was my idea but is apparently not good enough
then putStrLn (_shoot choice Rock)
-- ^^^^^^
-- Couldn't match type ‘[Char]’ with ‘RPS’ Expected type: RPS Actual type: String
else putStrLn "Invalid choice."
isRPS
returns a boolean (carrying true or false) instead of a more informative type (carrying the RPS value or an error). In this caseMaybe RPS
suffices. Sometimes you wantEither SomeError RPS
, if you have multiple errors to return.Bool
is not used so frequently in Haskell as in some other languages. – chi