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

Кортежные функции

Простейшие кортежные функции включают, по сути, только две функции: fst и snd:

fst :: (a,b) -> a

snd :: (a,b) -> b

Обе функции берут кортеж, только первая возвращает первый элемент кортежа, а вторая, кхм... второй, что ли? Проверим:

fst (23,"hello") → 23

snd (23,"hello") → "hello"

Отлично, а где же функция для создания кортежа? А нет такой, собственно. Если нужно создать кортеж из двух значений x и y – надо просто записать их в скобках и разделить запятыми: (x,y).

Из кортежных функций нужно еще обязательно упомянуть функции zip и unzip, мы обязательно их рассмотрим позднее.

Создание своих функций

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

Способ 1. Определение функции как выражения от параметров:

fact x = x * fact (x-1)

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

Способ 2. Несколько определений одной функции:

fact 0 = 1

fact x = x * fact (x-1)

Оказывается, функцию можно задать не одним определением, а несколькими. Как компилятор или интерпретатор языка сможет разобраться, какое определение ему использовать, если вы, например, захотели вычислить значение fact 4? Интуитивно понятно, что для вычисления значения fact 4 первое определение нам "не подходит". Чуть позже, когда мы будем говорить об образцах, мы уточним, что это такое "не подходит", а в самом конце курса найдем то единственное абсолютно логичное объяснение, которое и может быть в таком строгом и логичном языке, как Haskell. А пока просто запомним, что если определений несколько – берется первое из них, которое "подходит", то есть позволяет вычислить требуемое значение.

Способ 3. Определение функции через синоним:

productMy = product

Тут все просто – если уже есть какая-то функция product, то мы можем дать ей новое имя productMy. Ну, или по-другому, – можем объявить, что под именем productMy скрывается значение product, имеющее тип функции Num a => [a] -> a.

Ту же самую функцию можно было написать и по-другому:

productMy xs = product xs

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

Вспомните пример с функцией как ящиком-преобразователем на колесиках! Во втором случае мы описываем, что наш требуемый ящик на колесиках должен делать с тем списком чисел xs, который ему передали – он должен в свою очередь передать этот список функции product, подождать результата, и, в свою очередь, вернуть его. Мы работаем так, как привыкли в любом императивном языке – на уровне данных, передаваемых туда-сюда между функциями и переменными.

А вот в первом случае мы работаем на уровне функций! Мы описываем, как скомпоновать наш требуемый ящик на колесиках из уже имеющихся ящиков – в то время, когда никаких данных еще нет! Чувствуете разницу?

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