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

标签 haskell pattern-matching

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

一般情况如下,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"

我想知道如何挑出 split 的案例。

最佳答案

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

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)

关于函数 (+) (-) (/) (*) 的 Haskell 模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67952496/

相关文章:

haskell - 将列表转换为单独的参数

list - Haskell - 如何在排序后从元组列表中取出 n 项

php - 如何将长数字字符串分成月份

rust - 是否有评估可反驳模式是否匹配的简写?

perl 模式一一匹配并处理

haskell - 从用户输入中读取 float 或字符串

haskell - 合理的 Comonad 实现

Haskell + StablePtr

Scala模式匹配元组: matching equal values in the tuple

java - 我从哪里开始进行文本模式识别 - 基于 Java