1

データ型がある場合

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 ++ ")" 

関数 evaluate は次のように動作することが期待されます:

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 ではまだ新しいです。

ありがとう。

4

2 に答える 2

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

于 2013-09-26T18:45:22.123 に答える