Search code examples
haskellpattern-matchingalgebraic-data-typesdo-notation

Comparison of custom data type with parameters


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?


Solution

  • 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