Reputation: 1423
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
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