1

I am learning Haskell and trying to implement this program. I have a custom data type

data CalculatorInput 
    = Exit 
    | Error String 
    | Operator (Int -> Int -> Int)
    | Number Int

then I have a method getInput which returns a value of this type.

Now i am confused how to dispatch on values of this type. I have a method

simpleCalculator :: Int -> (Int -> Int -> Int) -> IO ()
simpleCalculator ans op =  do
    input <- getInput   -- here i got the type as result
    if input == Exit then return()
    else if input == Number x then ans = ans op x; print ans
    else simpleCalculator ans op

I want to know whether the input is a Number x

I tried to use case as well:

simpleCalculator :: Int -> (Int -> Int -> Int) -> IO ()
simpleCalculator ans op =  do
    input <- getInput   -- here i got the type as result
    --case input of
    --  Exit -> return ()
    --  Error x -> print x
    --  Number n -> ans = ans op x; print ans  -- getting error here, multiple statement not possible
    --  _ -> simpleCalculator ans op

I tried to create instance of Eq as well

instance Eq CalculatorInput where
    (==) Exit Exit = True
    (==) (Number x) (Number y) = x == y
    (==) _ _ = False 

How can I compare custom data types with parameters or have multiple statements in a case branch?

Cactus
  • 27,075
  • 9
  • 69
  • 149
Waqar Ahmed
  • 5,005
  • 2
  • 23
  • 45
  • @MathematicalOrchid. it didn't work. I tried. and i also notice it goes to inifnite loop on let ans = op ans n – Waqar Ahmed May 08 '16 at 16:32
  • 1
    @WaqarAhmedm `let ans = op ans n` -- This *recursively* defines `ans` in terms of itself. You need to use a new name, in this case we often use a prime `'`: `let ans' = op ans n` – luqui May 09 '16 at 03:00
  • @luqui..i got it..thanks. one more question, why it is consider good not to return value from simpleCalculator method? – Waqar Ahmed May 09 '16 at 10:32

2 Answers2

1

You're almost on the right track with your non-working code:

simpleCalculator :: Int -> (Int -> Int -> Int) -> IO ()
simpleCalculator ans op =  do
    input <- getInput   -- here i got the type as result
    case input of
      Exit -> return ()
      Error x -> print x
      Number n -> ans = ans op x; print ans
      _ -> simpleCalculator ans op

You can nest do notations allowing you to write the following correct program:

simpleCalculator :: Int -> (Int -> Int -> Int) -> IO ()
simpleCalculator ans op =  do
    input <- getInput   -- here i got the type as result
    case input of
      Exit -> return ()
      Error x -> print x
      Number n -> do
        let theAns = ans op x
        print theAns
      _ -> simpleCalculator ans op

As for the Eq instance, you can let the compiler do the work for you by using derivation, i.e. writing

data CalculatorInput 
    = Exit 
    | Error String 
    | Operator (Int -> Int -> Int)
    | Number Int
    deriving Eq
Cactus
  • 27,075
  • 9
  • 69
  • 149
  • Hi cactus, i tried this same logic yesterday and it worked. but i am confused, if i use ans = ans op x. it goes to infinite loop. can you please tell me why it is happening. – Waqar Ahmed May 09 '16 at 10:30
  • That's because if you do `let ans = ans op x`, the `ans` on the right-hand side refers to the same `ans` being defined. – Cactus May 09 '16 at 11:26
  • Thank you, i got it...one more question, why it is consider good not to return value from method such as in this case simpleCalculator method? – Waqar Ahmed May 09 '16 at 14:29
0

Use case.

simpleCalculator ans op =  do
    input <- getInput   -- here i got the type as result
    case input of
        Exit -> return ()
        Number x -> print $ans `op` x
        _ -> simpleCalculator ans op

You cannot derive Eq for CalculatorInput because functions are not instances of Eq.

bipll
  • 11,747
  • 1
  • 18
  • 32