Haskell 函数的模式匹配 (+) (-) (/) (*)

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

对于函数定义,我需要在检测到被零除时输出错误。

一般情况如下,op取(+),(-),(*),(/)函数。

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

用例是

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

但是我尝试检测除以 0 的特殊情况。我的解决方案是

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

但第一个分支似乎匹配任何运算符。

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

不知如何挑出除法的案例

首先,你在 (/) 上的模式匹配不起作用,因为 GHC 认为你想将该参数绑定到名称 (/) 并覆盖 (/) 的通常绑定。看这个更简单的例子:

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

正如 Willem Van Onsem 在评论中指出的那样,处理此问题的常用方法是引入要匹配的所有函数的枚举数据类型:

data Operation = Add | Sub | Mul | Div

此外,您还需要为这些操作赋予语义(意义):

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

那么你可以定义liftIntOp为:

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