2013-09-25 4 views
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 ++ ")" 

и функция оценивать, которая, как ожидается, ведем себя как:

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 определяется как Добавить Arith Arith, Sub Arith Arith, так как я могу воспользоваться этим в своей функции eval? Я пробовал делать:

eval (Add Arith Arith) = Arith + Arith 

Но это тоже не сработало (не в области ошибки).

Вам не нужно давать мне пример полного рабочего кода или что-то еще, я просто пытаюсь получить указатель в правильном направлении. Еще новенькая в haskell.

Спасибо.

ответ

6

Вы должны использовать рекурсию.

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

и т.д ..

+1

О, я не уверен, почему я об этом не думал. Я так новичок в haskell, что я автоматически не думаю, что рекурсивно. Что-то, над чем мне нужно работать. Это работает и из того, что я понимаю, базовый случай - это просто eval (Con i) = i – Harrison

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.

Смежные вопросы