Skip to content

Commit

Permalink
Update 17.txt
Browse files Browse the repository at this point in the history
  • Loading branch information
bach741974 committed Jun 24, 2013
1 parent 681991b commit 230da73
Showing 1 changed file with 20 additions and 18 deletions.
38 changes: 20 additions & 18 deletions pandoc/17.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ appendFiles file1 file2 resFile = writeFile resFile =<<
## Расширения

Расширение появляется в ответ на проблему, с которой трудно
или невозможно справится
или невозможно справиться
в рамках стандарта Haskell. Мы рассмотрим несколько
наиболее часто используемых расширений.
Расширения подключаются с помощью специального
Expand All @@ -277,15 +277,15 @@ appendFiles file1 file2 resFile = writeFile resFile =<<
{-# LANGUAGE ExtentionName1, ExtentionName2, ExtentionName3 #-}
~~~

Обратите внимание на символ решётка, обрамляющие комментарии.
Обратите внимание на символ решётки, обрамляющего комментарии.
Слово `LANGUAGE` говорит компилятору о том, что мы хотим
воспользоваться расширениями с именами `ExtentionName1`,
`ExtentionName2`, `ExtentionName3`.
Такой комментарий называется *прагмой* (pragma).
Часто компилятор ghc в случае ошибки предлагает
нам подключить расширение, в котором ошибка уже не будет
ошибкой, а возможностью языка. Он говорит возможно вы
имели в виду расширение `XXX`. Например попробуйте
ошибкой, а возможностью языка. Он говорит: возможно, вы
имели в виду расширение `XXX`. Например, попробуйте
загрузить в интерпретатор модуль:

~~~
Expand All @@ -310,7 +310,7 @@ Failed, modules loaded: none.
Компилятор сообщает нам о том, что у нас слишком
много параметров в классе `Multi`. В рамках стандарта
Haskell можно создавать лишь классы с одним параметром.
Но за сообщением мы видим подсказку, если мы воспользуемся
Но за сообщением мы видим подсказку: если мы воспользуемся
расширением `-XMultiParamTypeClasses`, то всё будет хорошо.
В этом сообщении имя расширения закодировано в виде флага.
Мы можем запустить ghc или ghci с этим флагом и тогда
Expand Down Expand Up @@ -372,10 +372,10 @@ data Exp = ValTrue
В этом определении кроется одна проблема. Наш тип
позволяет нам строить бессмысленные выражения
вроде `Add ValTrue (Val 2)` или `If (Val 1) ValTrue (Val 22)`.
Наш тип `Val` включает в себя все хорошие выражения и
Наш тип `Exp` включает в себя все хорошие выражения и
много плохих. Эта проблема проявится особенно ярко, если
мы попытаемся определить функцию `eval`, которая
вычисляет значение для нашего языка. Получается, что
вычисляет значения для нашего языка. Получается, что
тип этой функции:

~~~
Expand All @@ -385,8 +385,8 @@ eval :: Exp -> Either Int Bool
\Types{обобщённые алгебраические типы данных, GADT}
Для решения этой проблемы были придуманы *обобщённые алгебраические
типы данных* (generalised algebraic data types, GADTs). Они подключаются
расширением `GADTs`. Помните когда-то мы говорили, что типы
можно представить в виде классов. Например определение для списка
расширением `GADTs`. Помните, когда-то мы говорили, что типы
можно представить в виде классов. Например, определение для списка

~~~
data List a = Nil | Cons a (List a)
Expand All @@ -403,7 +403,7 @@ data List a where
Так вот в GADT определения записываются именно в таком виде.
Обобщение заключается в том, что теперь на месте произвольного
параметра `a` мы можем писать конкретные типы. Определим
тип `GExp`
тип `Exp`

~~~
{-# LANGUAGE GADTs #-}
Expand Down Expand Up @@ -473,11 +473,11 @@ Haskell очень часто применяется для построения
чтобы только потом получить то, что мы могли вычислить и напрямую.

При таком подходе у нас есть полный контроль за деревом
выражения, мы можем проводить дополнительную оптимизацию
выражения: мы можем проводить дополнительную оптимизацию
выражений, если нам известны некоторые закономерности.
Ещё функция `eval` может вычислять совсем другие значения.
Например она может по виду выражения составлять код на другом языке.
Возможно этот язык гораздо
Например, она может по виду выражения составлять код на другом языке.
Возможно, этот язык гораздо
мощнее Haskell по вычислительным способностям, но беднее в плане
выразительности, гибкости синтаксиса. Тогда мы будем в функции
`eval` проецировать разные конструкции Haskell в конструкции
Expand Down Expand Up @@ -522,7 +522,7 @@ class Arith exp where

Интерпретация дерева выражения в этом подходе
заключается в создании экземпляра класса.
Например создадим класс-вычислитель `Eval`:
Например, создадим класс-вычислитель `Eval`:

~~~
newtype Eval a = Eval { runEval :: a }
Expand All @@ -545,7 +545,7 @@ instance E Eval

~~~
notE :: Log exp => exp Bool -> exp Bool
notE x = iff x true false
notE x = iff x false true

squareE :: Arith exp => exp Int -> exp Int
squareE x = mul x x
Expand All @@ -569,7 +569,7 @@ Ok, modules loaded: Exp.
False
~~~

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

Expand All @@ -587,6 +587,8 @@ 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 ++ ")"

instance E Print
~~~

Теперь распечатаем предыдущие выражения:
Expand All @@ -602,8 +604,8 @@ Ok, modules loaded: Exp.
"if (True) {False}{True}"
~~~

При таком подходе нам не пришлось ничего менять в выражениях,
мы просто заменили тип выражения и оно автоматически подстроилось под
При таком подходе нам не пришлось ничего менять в выражениях:
мы просто заменили тип выражения, и оно автоматически подстроилось под
нужный результат. Подробнее об этом подходе можно почитать
на сайте <http://okmij.org/ftp/tagless-final/course/course.html>
или в статье Жака Каре (Jacques Carette), Олега Киселёва (Oleg Kiselyov) и
Expand Down

0 comments on commit 230da73

Please sign in to comment.