52700.fb2
class E exp where
true
:: exp Bool
false
:: exp Bool
iff
:: exp Bool -> exp a -> exp a -> exp a
val
:: Int -> exp Int
add
:: exp Int -> exp Int -> exp Int
mul
:: exp Int -> exp Int -> exp Int
Преимуществом такого подхода является модульность. Мы можем спокойно разделить выражение на две
составляющие части:
class (Log exp, Arith exp) => E exp
class Log exp where
true
:: exp Bool
false
:: exp Bool
iff
:: exp Bool -> exp a -> exp a -> exp a
class Arith exp where
val
:: Int -> exp Int
add
:: exp Int -> exp Int -> exp Int
mul
:: exp Int -> exp Int -> exp Int
Интерпретация дерева выражения в этом подходе заключается в создании экземпляра класса. Например
создадим класс-вычислитель Eval:
newtype Eval a = Eval { runEval :: a }
instance Log Eval where
256 | Глава 17: Дополнительные возможности
true
= Eval True
false
= Eval False
iff p t e = if runEval p then t else e
instance Arith Eval where
val
= Eval
add a b = Eval $ runEval a + runEval b
mul a b = Eval $ runEval a * runEval b
instance E Eval
Теперь проведём такую же сессию вычисления значений, но давайте теперь сначала определим их в тексте
программы:
notE :: Log exp => exp Bool -> exp Bool