Язык Haskell: О пользе и вреде лени: различия между версиями
Содержимое удалено Содержимое добавлено
мНет описания правки |
|||
Строка 1:
:<small>Исходная версия статьи (Ворожцов
▲===Аннотация===
[[Изображение:2_1.jpg|right|]]
В большинстве российских школ на уроках программирования изучают
Строка 62 ⟶ 63 :
ячеек друг от друга, и в одной из ячеек получаем нужный нам
результат.
Программа на языке Haskell представляет
Строка 149:
<tt> (Float->Float)->Float</tt> соответствует функции, которая получает на вход функцию
типа <tt> Float->Float</tt> и возвращает действительное число.
Интересно заметить, что при конструировании новых типов с помощью операций
<tt> [a]</tt>, <tt> (a,b)</tt> и <tt> a->b</tt> не обязательно вместо <tt> a</tt> и <tt> b</tt>
Строка 159 ⟶ 158 :
и возвращает список пар элементов типа <tt> a </tt>и <tt> b</tt>.
=== Пример 1
Функция <tt>inc<tt> увеличивает число на единицу. Она
определяется следующим образом:
Строка 173 ⟶ 172 :
inc :: Integer->Integer
=== Пример 2
Функция <tt>add<tt> находит сумму данных ей чисел.
Аргументами этой функции являются два числа:
Строка 191:
разделяются просто пробелами, а не запятыми, как в языках Си или Паскаль.
=== Пример 3
Есть два способа обозначения списков — квадратные скобки, в которых перечислены
элементы через запятую, или круглые скобки, в которых элементы разделены двоеточием. В частности
Строка 212 ⟶ 213 :
но показательный.
=== Пример 4
Рассмотрим функцию <tt> map</tt>, которая получает на вход функцию и список элементов,
а в качестве результата возвращает список элементов, к которым применена данная функция:
Строка 234 ⟶ 236 :
<tt> map (\ x -> x*x*x ) [1,2,3] ) ''<math>\Rightarrow</math>'' [1,8,27].</tt>
А вот простой способ найти первые 5 степеней двоек:
<tt> take 5 powers where powers = map (2 ^) [1..] ''<math>\Rightarrow</math>'' [2,4,8,16,32].</tt>
▲Есть другой способ определения функции <tt> map</tt>:
Это соответствует математической записи <math>map(f,xs) = \left\{ f(x) | x\in xs \right\}.</math>▼
▲«<tt> map f xs = [ f x | x <- xs]</tt>».
▲Это соответствует математической записи
▲Конструкция «<tt> x<-xs</tt>» называется «генератором», её
следует интерпретировать как «элемент <tt> x </tt>берётся из списка <tt> xs</tt>».
Строка 283 ⟶ 282 :
Например, в языке Mathematica (http://wolfram.com) для определения функций используется «<tt> :=</tt>»,
а для присваивания — просто «<tt> =</tt>».
Рассмотрим функцию <tt> numsFrom</tt>, которая получает один
Строка 305 ⟶ 302 :
<tt> take 5 squares ''<math>\Rightarrow</math>'' [0,1,4,9,16].</tt>
Функцию <tt>take</tt> можно было определить рекурсивно:
Строка 334 ⟶ 330 :
так как ''11 = 1 + 2 + 8 = 2^0 + 2^1 + 2^3'', а для ''255'' ответ должен быть равен 8,
так как ''255=1 + 2 + 4 + ... + 64 + 128'' есть сумма восьми различных степеней двойки.
Введём следующие определения.
Строка 350 ⟶ 345 :
Стандартная функция <tt> reverse</tt> обращает список: получает на вход список и возвращает тот же
список, в котором элементы идут в обратном порядке, начиная с последнего до первого:
{|
Строка 373 ⟶ 367 :
|8.
|}
Для того, чтобы найти сами степени двойки, в сумму которых разлагается
Строка 436 ⟶ 429 :
Несмотря на свою «серьёзность», выглядит он подозрительно просто:
--Быстрая сортировка на языке Haskell
qsort [] = []
Строка 444 ⟶ 436 :
qsort [y | y <- xs, y>=x]
Поясним смысл этих строчек. Запись «<tt> qsort [] = [] </tt> » означает, что если на вход дан пустой
список <tt>[]</tt>, то и в результате будет пустой список. В следующей строчке рассматривается случай,
Строка 456 ⟶ 447 :
Тот же самый алгоритм на языке Си занимает далеко не
4 строчки:
/* Быстрая сортировка на языке Си */
void qsort( a, lo, hi )
▲ {
int a[], hi, lo; {
int h, l, p, t;
Строка 486 ⟶ 477 :
qsort( a, lo, l-1 );
qsort( a, l+1, hi );
▲ }
Таким образом, на языке Haskell многие алгоритмы можно запрограммировать существенно быстрее, нежели на Си или Паскале.
Строка 503 ⟶ 492 :
http://wtk.norilsk.net/pm/fp/haskell.html, http://www.haskell.ru/.
== Дистрибутивы Haskell ==
Строка 509 ⟶ 497 :
Все они распространяются бесплатно.
Рекомендуем начать с маленького и удобного для обучения интерпретатора Hugs (http://haskell.org/hugs).
== Зачем нужно функциональное программирование? ==
Строка 524 ⟶ 511 :
* создаются адаптивные, легко изменяемые и расширяемые программы.
Кроме того, отмечается, что благодаря строгой типизации языка, в программах на
Haskell не случается системных ошибок и не бывает аварийных ситуаций (<tt> сore dump</tt>).
Строка 539 ⟶ 525 :
Мощь, которую предоставляет это исчисление,
ещё не до конца осознана программистами и не в полной мере используется на практике.
Обратите внимание на то, что в списке достоинств не указаны такие
Строка 562 ⟶ 547 :
программирования в качестве одного из важных достоинств языка
указывают его близость к естественному языку (обычно английскому).
== Встроенное управление памятью ==
Строка 618 ⟶ 602 :
и «научить» трансляторы функциональных языков программирования «видеть их» в определениях функций
и применять известные эффективные алгоритмы вычисления.
Конечно, язык Си предпочтительнее в целом ряде случаев: системное программирование, драйверы устройств, приложения, от которых требуется высокая производительность, например, компьютерные игрушки с качественной графикой и др. Но всё это довольно специальные случаи.
Строка 634 ⟶ 617 :
Система работает на мейнфреймах IBM.
* Компания Ericsson разработала функциональный язык Erlang для создания системы управления телефонных станций.
* Исследователи в корпорации MITRE используют Haskell
Для многих программистов не секрет, что на процедурных языках
можно писать объектно-ориентированным образом, а на
Строка 673 ⟶ 654 :
== Примечания ==
# {{note|cons}} Когда в языке Си определяется переменная типа функции, необходимо указать типы аргументов функции и тип возвращаемого значения. Например, «<tt> int (*)(int, int) </tt>» — это тип функции, возвращающей число типа <tt> int </tt> и принимающей в качестве аргументов два числа типа <tt> int </tt>.
# {{note|cons}} Прототипирование — это быстрая «черновая» реализация базовой функциональности для анализа работы системы в целом. Для прототипирования используют языки высокого уровня абстракции (Java, Perl, Python, Haskell, ...). После этапа прототипирования обязательно следуют этапы пересмотрения архитектуры системы, разработки, реализации и тестирования конечного продукта. На этапе разработки подготавливают систему тестов, по работе которых буду судить о качестве продукта. При реализации решения обычно используют другой, «более машинноориентированный» язык программирования (Си, Си++, ...), пишут более аккуратный,документированный код, а на тестирование системы тратят сравнительно большое количество усилий для достижения качественного результата.
|