52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 285

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 285

notE x = iff x true false

squareE :: Arith exp => exp Int -> exp Int

squareE x = mul x x

e1 :: E exp => exp Int

e1 = squareE $ iff (notE true) (val 1) (val 2)

e2 :: E exp => exp Bool

e2 = notE true

Загрузим в интерпретатор:

*Exp> :r

[1 of 1] Compiling Exp

( Exp. hs, interpreted )

Ok, modules loaded: Exp.

*Exp> runEval e1

4

*Exp> runEval e2

False

Получились такие же результаты и в этом случае нам не нужно подключать никаких расширений. Теперь

создадим тип-принтер, он будет распечатывать выражение:

newtype Print a = Print { runPrint :: String }

instance Log Print where

true

= Print ”True”

false

= Print ”False”

iff p t e = Print $ ”if (” ++ runPrint p ++ ”) {”

++ runPrint t ++ ”}”

++ ”{” ++ runPrint e ++ ”}”

instance Arith Print where

val n

= Print $ show n

add a b = Print $ ”(” ++ runPrint a ++ ”)+(” ++ runPrint b ++ ”)”

mul a b = Print $ ”(” ++ runPrint a ++ ”)*(” ++ runPrint b ++ ”)”

Теперь распечатаем предыдущие выражения:

*Exp> :r

[1 of 1] Compiling Exp

( Exp. hs, interpreted )

Ok, modules loaded: Exp.

*Exp> runPrint e1

”(if (if (True) {False}{True}) {1}{2})*(if (if (True) {False}{True}) {1}{2})”

*Exp> runPrint e2

”if (True) {False}{True}”

При таком подходе нам не пришлось ничего менять в выражениях, мы просто заменили тип выражения

и оно автоматически подстроилось под нужный результат. Подробнее об этом подходе можно почитать на

сайте http://okmij.org/ftp/tagless-final/course/course.html или в статье Жака Каре (Jacques Carette), Олега Киселёва (Oleg Kiselyov) и Чунг-Че Шена (Chung-chieh Shan) Finally Tagless, Partially Evaluated.

Расширения | 257

Семейства типов

Семейства типов позволяют выражать зависимости типов. Например представим, что класс определяет

не только методы, но и типы. Причём новые типы зависят от конкретного экземпляра класса. Посмотрим,

например, на определение линейного пространства из библиотеки vector-space:

class AdditiveGroup v where