HarryQ
HarryQ

Reputation: 1423

Haskell Pattern Matching for fuctions (+) (-) (/) (*)

For a function definition, I need to output a error when division by zero is detected.

The general case is as follows, op takes the (+), (-), (*), (/) function.

liftIntOp :: (Int->Int->Int)->Val->Val->Val
liftIntOp op (IntVal a) (IntVal b) =IntVal $ op a b

The use case is

Main>liftIntOp (+) (IntVal 3) (IntVal 5)
Main>IntVal 8

However I try to detect the special case of division by 0. My solution is

liftIntOp :: (Int->Int->Int)->Val->Val->Val
liftIntOp (/) _ (IntVal 0) =ErrorVal "Division by 0"
liftIntOp op (IntVal a) (IntVal b) =IntVal $ op a b

But the first branch seems to match any operators.

Main> liftIntOp (-) (IntVal 3) (IntVal 0)
Main> ErrorVal "Division by 0"
Main> liftIntOp (+) (IntVal 3) (IntVal 0)
Main> ErrorVal "Division by 0"

I wonder how to single out the case for division.

Upvotes: 3

Views: 286

Answers (1)

Noughtmare
Noughtmare

Reputation: 10655

Firstly, your pattern match on (/) does not work, because GHC thinks you want to bind that argument to the name (/) and overwrite the usual binding of (/). See this simpler example:

ghci> let foo (/) x y = x / y
ghci> foo (+) 1 2
3

As Willem Van Onsem noted in the comments, the usual way to deal with this is to introduce an enumeration data type of all the functions that you want to match against:

data Operation = Add | Sub | Mul | Div

Additionally you then need to give semantics (meaning) to those operations:

applyIntOp :: Operation -> Int -> Int -> Int
applyIntOp Add = (+)
applyIntOp Sub = (-)
applyIntOp Mul = (*)
applyIntOp Div = div -- note that (/) doesn't work on Int

Then you can define liftIntOp as:

liftIntOp :: Operation -> Val -> Val -> Val
liftIntOp Div _ (IntVal 0) = ErrorVal "Division by zero"
liftIntOp op (IntVal x) (IntVal y) = IntVal (applyIntOp op x y)

Upvotes: 2

Related Questions