Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MakeevGA-Haskell-a4-shortcode_2014_05_31.doc
Скачиваний:
16
Добавлен:
19.01.2023
Размер:
1.79 Mб
Скачать

Кортежи

Кортежи, в отличие от списков, могут содержать разнотипные элементы, но их обязательно фиксированное число. Кортеж является, по сути, аналогом записи в императивных языках, только без названий у полей:

(1,'a') :: (Integer, Char)

(True,1) :: (Bool, Integer)

("Vladimir",12,[5,5,5]) :: (String, Integer, [Integer])

Функции, операторы

Что такое функция? В привычном для нас всех смысле, функция – это механизм, который умеет преобразовывать одни данные в другие. Это может быть удивительным для тех, кто привык к императивным языкам, но функции тоже относят к данным, потому что ими можно манипулировать, как любыми другими данными (если встретите труднопереводимое на русский язык выражение "a function is a first-class citizen" – оно именно об этом).

Удобно представлять себе функции как большие передвижные ящики-преобразователи на колесиках, у которых есть одно или несколько входных отверстий и одно выходное.

Большую часть времени ящик простаивает, но если ему во входные отверстия вложить требуемые материалы, то ящик заработает и выкинет в выходное отверстие что-то новое, что является результатом преобразования исходных материалов.

В такой аналогии становится понятно, почему с функциями можно обращаться так же как с любыми другим данными: складывать в списки и кортежи, передавать в другие функции и получать как результат из третьих функций.

Функция – это специфическое значение. Значение – потому что ее нельзя дальше упростить, вычислить в нечто более простое (напоминаю, функция – это ящик с отверстиями). А специфическое – потому что в отличие от, скажем, числа, которое нельзя ни для чего особенного применить (только принять к сведению как ответ), функцию можно применить к значениям для получения других значений. В функцию можно передать значения, чтобы получить другие значения, вот так:

mod 5 3 → 2

Обратите внимание, вызов функции не требует никаких скобок, даже если этих аргументов несколько. Более того, если одиночный аргумент можно и взять в скобки sin (5), то в случае двух аргументов что mod (5 3), что mod (5,3) будет ошибкой.

Но вернемся к самой функции. Раз функция – это значение, а любое значение имеет тип, то мы должны говорить о типе функции. Раз функция принимает значения, имеющие тип, то мы должны говорить о типе параметров функции. Собственно, вместо всех этих слов можно было просто сказать, что тип функции – это совокупность типов всех ее параметров и типа результата:

sin :: Float -> Float

ord :: Char -> Int

Что нам говорит эта запись? Нечто, скрывающееся под именем sin – это функция, принимающая значение типа Float, и возвращающая значение типа Float. Заметим, что тип этой функции не говорит нам ничего о том, что эта функция делает. Несмотря на это, чаще всего по имени функции и по типу ее параметров можно догадаться о ее назначении. Так, ord – это функция, принимающая значение типа Char и возвращающая значение типа Int, а название говорит нам о том, что скорее всего эта функция возвращает порядковый номер символа (конечно же, в таблице ASCII).

(+) :: Float -> Float -> Float

Несколько стрелочек говорят нам о том, что перед нами функция нескольких параметров. В данном случае (+) – это функция, берущая два значения типа Float, и возвращающая значение типа Float.

Последняя стрелка в данном случае указывает на тип результата, а все предыдущие стрелки разделяют входные параметры.

Правда, "логично"? Стрелка одна и та же, но в одном случае она означает "входной параметр", а в другом случае "результат"? На самом деле в языке Haskell все очень строго и логично, без всяких кавычек, и эту кажущуюся несуразность мы очень скоро ликвидируем.