【问题标题】:Data types and non exhaustive patterns数据类型和非详尽模式
【发布时间】:2013-09-25 17:57:02
【问题描述】:

如果有数据类型

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还是新手。

谢谢。

【问题讨论】:

    标签: haskell


    【解决方案1】:

    你应该使用递归。

    eval (Add a1 a2) = (eval a1) + (eval a2)
    

    等等。

    【讨论】:

    • 啊,好吧,我不知道为什么我没有考虑到这一点。我对 haskell 很陌生,以至于我不会自动递归地思考。我需要做的事情。这行得通,据我了解,基本情况只是 eval (Con i) = i
    【解决方案2】:

    这里进行一些重构以减少重复:

    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 也可以这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-04
      • 2021-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多