Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Характеристики языка




В качестве основных характеристик языка Haskell можно выделить следующие:

  • недопустимость побочных эффектов (чистота языка); возможность писать программы с побочными эффектами без нарушения парадигмы функционального программирования с помощью монад;
  • статическая сильная полная типизация с автоматическим выведением типов, основанная на типизации Хиндли — Милнера;
  • функции высшего порядка, в том числе лямбда-абстракции;
  • частичное применение;
  • ленивые вычисления (lazy evaluation);
  • сопоставление с образцом (англ. pattern matching), функциональные образцы, охраняющие выражения (guards);
  • параметрический полиморфизм и его объедение с ad hoc полиморфизмом в единую модель посредством классов типов;
  • алгебраические типы данных, в том числе псевдобесконечные (за счёт ленивости);
  • генераторы списков (list comprehensions);
  • возможность интеграции с программами, реализованными на императивных языках программирования посредством открытых интерфейсов (стандартное расширение языка Foreign Function Interface [16]

С момента принятия последнего стандарта языка (Haskell98) прошло много времени, и с тех пор ведущие реализации языка (ghc и hugs) были расширены множеством дополнительных возможностей:

  • параметрический полиморфизм высших рангов за счёт квантификации переменных типа (вплоть до импредикативного) — естественно, исключающая выведение типов.
  • Функциональные зависимости (FD, functional dependencies)[3]

Переменных в Haskell нет, это одна из причин, почему язык Haskell называют «чистым». Переменных нет, но можно определять функции, которые не получают аргументов и возвращают числа. Именно так следует интерпретировать символы x и y в последнем примере — это функции, а не переменные. Знак равенства = имеет в Haskell принципиально другое значение, нежели операция присвоения = в языке Си (или аналогичная операция:= в Паскале). В языке Си эта операция интерпретируется следующим образом: вычислить то, что указано справа от знака «равно», и результат поместить в переменную (ячейку памяти), которая указана слева от знака «равно». Строка

x = x + 2

в языке Си интерпретируется как команда «увеличить значение переменной x на 2». В языке Haskell смысл этой команды совсем другой — «определить функцию x следующим образом: результат функции равен сумме результата вычисления функции x и числа 2». То есть в языке Haskell эта строка является определением рекурсивной функции с именем x!!! Функция x определена через себя, и использование этой функции приведёт к бесконечной цепочке рекурсивных вызовов и к ошибке переполнения стека «stack overflow»:

> x where x = x + 2ERROR - stack overflow.

В языке Haskell нет переменных и нет понятия состояния — множества значений всех текущих переменных. Как жить в таких необычных и жёстких условиях?! Рассмотрим ряд простых примеров.

В этом языке программирования есть базовые типы: Integer (целое число), Char (символ), Double (число с плавающей точкой, ранее обозначалось Float). Есть специальные конструкции (), [] и ->, которые позволяют определять новые типы на основании существующих.

Пусть a и b являются некоторыми типами данных. Тогда конструкция [a] означает новый тип — список элементов типа a. В частности тип String есть синоним типа [Char].

Конструкция (a, b) означает тип пары элементов типов a и b. Соответственно можно задавать типы троек, четвёрок и произвольных наборов (кортежей) из n {\displaystyle n} элементов.

Конструкция a -> b соответствует типу функций, которые получают на входе элемент типа a и возвращают элемент типа b.

Примеры типов:

Integer -> Integer целочисленная функция целого аргумента;
[Integer] -> Float функция, которая получает список целых чисел, а возвращает действительное число типа Float;
Float -> Float -> Float функция, которая получает на входе два действительных числа и возвращает действительное число;
(Float, Integer) -> [(Float, Float)] функция, которая получает на входе пару чисел типа Float и Integer и возвращает список пар чисел типа Float.

Особый интерес представляет тип Float -> Float -> Float. Его можно интерпретировать и по-другому: функция, которая получает одно число типа Float и возвращает функцию типа Float -> Float. Действительно, если у функции с двумя аргументами зафиксировать один аргумент, то получится функция одного аргумента.

При конструировании типов можно использовать круглые скобки, чтобы обозначить неделимые элементы. Например, тип (Float -> Float) -> Float соответствует функции, которая получает на вход функцию типа Float -> Float и возвращает действительное число.

Интересно заметить, что при конструировании новых типов с помощью операций [a], (a, b) и a -> b не обязательно вместо a и b подставлять конкретные существующие типы. Можно использовать маленькие латинские буквы, означающие произвольный тип. В частности, тип a -> b -> [(a, b)] означает функцию, которая получает на входе два элемента типов a и b и возвращает список пар элементов типа a и b.[3]






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных