如果有数据类型
data Arith = Con Int
| Add Arith Arith
| Sub Arith Arith
| Mul Arith Arith
| Div Arith Arith
一个实例:
instance Show Arith where
show (Con i) = show i
show (Add e1 e2) = "(" ++ show e1 ++ " + " ++ show e2 ++ ")"
show (Sub e1 e2) = "(" ++ show e1 ++ " - " ++ show e2 ++ ")"
show (Mul e1 e2) = "(" ++ show e1 ++ " * " ++ show e2 ++ ")"
show (Div e1 e2) = "(" ++ show e1 ++ " / " ++ show e2 ++ ")"
和函数评估预期的行为如下:
ghci> eval (Mul (Con 5) (Div (Con 6) (Con 2) ))
15
当我尝试比基本案例更复杂的事情时,这就是我提出的那些不起作用的事情。
eval :: ArithExp -> Int
eval (Con e1) = e1
eval (Add (Con e1) (Con e2)) = e1 + e2
eval (Sub (Con e1) (Con e2)) = e1 - e2
eval (Div (Con e1) (Con e2)) = e1 `div` e2
eval (Mul (Con e1) (Con e2)) = e1 * e2
当我尝试在这种情况下没有的任何事情时,我当然会得到关于详尽模式的错误。
所以我的问题是,如何在没有天真的方式的情况下捕捉所有模式?
我注意到Add被定义为Add Arith Arith,Sub Arith Arith所以我如何在我的eval函数中利用它?我试过了:
eval (Add Arith Arith) = Arith + Arith
但那也没有用,(不在范围错误中)。
你不需要给我一个完整的代码示例或任何东西,我只是试图指出正确的方向。在haskell仍然是新的。
感谢。
答案 0 :(得分:6)
你应该使用递归。
eval (Add a1 a2) = (eval a1) + (eval a2)
等。
答案 1 :(得分:0)
这是一个减少重复的重构:
data OpT = Add | Sub | Mul | Div
data Arith = Con Int
| Op OpT Arith Arith
eval :: Arith -> Int
eval (Con a) = a
eval (Op f a b) = evalOp f (eval a) (eval b) where
evalOp Add = (+)
evalOp Sub = (-)
evalOp Mul = (*)
evalOp Div = div
您可以使用show
执行相同操作。