Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Несколько заключительных слов о классах типовСодержание книги
Поиск на нашем сайте
Поскольку класс типа определяет абстрактный интерфейс, один и тот же тип данных может иметь экземпляры для различных клас- сов, а для одного и того же класса могут быть определены экзем- пляры различных типов. Например, тип Char имеет экземпляры для многих классов, два из которых – Eq и Ord, поскольку мы можем сравнивать символы на равенство и располагать их в алфавитном порядке. Иногда для типа данных должен быть определён экземпляр не- которого класса для того, чтобы имелась возможность определить для него экземпляр другого класса. Например, для определения эк- земпляра класса Ord необходимо предварительно иметь экземпляр класса Eq. Другими словами, наличие экземпляра класса Eq является предварительным (необходимым) условием для определения экземпля- ра класса Ord. Если поразмыслить, это вполне логично: раз уж до- пускается расположение неких значений в определённом порядке, то должна быть предусмотрена и возможность проверить их на ра- венство.
СИНТАКСИС ФУНКЦИЙ
Сопоставление с образцом В этой главе будет рассказано о неко- торых весьма полезных синтаксических конструкциях языка Haskell, и начнём мы с сопоставления с образцом. Идея за- ключается в указании определённых шаб- лонов – образцов, которым должны соот- ветствовать некоторые данные. Во время выполнения программы данные проверя- ются на соответствие образцу (сопостав- ляются). Если они подходят под образец, то будут разобраны в соответствии с ним. Когда вы определяете функцию, её определение можно разбить на несколь- ко частей (клозов), по одной части для каждого образца. Это позволяет создать очень стройный код, простой и легко чи- таемый. Вы можете задавать образцы для любого типа данных – чи- сел, символов, списков, кортежей и т. д. Давайте создадим простую функцию, которая проверяет, является ли её параметр числом семь. lucky:: Int -> String lucky 7 = "СЧАСТЛИВОЕ ЧИСЛО 7!" lucky x = "Прости, друг, повезёт в другой раз!"
Когда вы вызываете функцию lucky, производится проверка па- раметра на совпадение с заданными образцами в том порядке, в ка- ком они были заданы. Когда проверка даст положительный резуль- тат, используется соответствующее тело функции. Единственный случай, когда число, переданное функции, удовлетворяет первому образцу, – когда оно равно семи. В противном случае проводится проверка на совпадение со следующим образцом. Следующий об- разец может быть успешно сопоставлен с любым числом; также он привязывает переданное число к переменной x. Если в образце вместо реального значения (например, 7) пишут идентификатор, начинающийся со строчной буквы (например, x, y или myNumber), то этот образец будет сопоставлен любому передан- ному значению. Обратиться к сопоставленному значению в теле функции можно будет посредством введённого идентификатора. Эта функция может быть реализована с использованием клю- чевого слова if. Ну а если нам потребуется написать функцию, ко- торая называет цифры от 1 до 5 и выводит "Это число не в пределах от 1 до 5" для других чисел? Без сопоставления с образцом нам бы пришлось создать очень запутанное дерево условных выражений if – then – else. А вот что получится, если использовать сопостав- ление: sayMe:: Int -> String sayMe 1 = "Один!" sayMe 2 = "Два!" sayMe 3 = "Три!" sayMe 4 = "Четыре!" sayMe 5 = "Пять!" sayMe x = "Это число не в пределах от 1 до 5" Заметьте, что если бы мы переместили последнюю строку опре- деления функции (образец в которой соответствует любому вводу) вверх, то функция всегда выводила бы "Это число не в пределах от 1 до 5", потому что невозможно было бы пройти дальше и провести проверку на совпадение с другими образцами. Помните реализованную нами функцию факториала? Мы оп- ределили факториал числа n как произведение чисел [1..n]. Мы можем определить данную функцию рекурсивно, точно так же, как факториал определяется в математике. Начнём с того, что объявим факториал нуля равным единице.
Затем определим факториал любого положительного числа как данное число, умноженное на факториал предыдущего числа. Вот как это будет выглядеть в терминах языка Haskell. factorial:: Integer -> Integer factorial 0 = 1 factorial n = n * factorial (n – 1) Мы в первый раз задали функцию рекурсивно. Рекурсия очень важна в языке Haskell, и подробнее она будет рассмотрена позже. Сопоставление с образцом может завершиться неудачей, если мы зададим функцию следующим образом: charName:: Char –> String charName 'а' = "Артём" charName 'б' = "Борис" charName 'в' = "Виктор" а затем попытаемся вызвать её с параметром, которого не ожидали. Произойдёт следующее: ghci> charName 'а' "Артём" ghci> charName 'в' "Виктор" ghci> charName 'м' "*** Exception: Non-exhaustive patterns in function charName Это жалоба на то, что наши образцы не покрывают всех возмож- ных случаев (недоопределены) – и, воистину, так оно и есть! Когда мы определяем функцию, мы должны всегда включать образец, кото- рый можно сопоставить с любым входным значением, для того что- бы наша программа не закрывалась с сообщением об ошибке, если функция получит какие-то непредвиденные входные данные.
Сопоставление с парами Сопоставление с образцом может быть использовано и для корте- жей. Что если мы хотим создать функцию, которая принимает два двумерных вектора (представленных в форме пары) и складывает их? Чтобы сложить два вектора, нужно сложить их соответствую- щие координаты. Вот как мы написали бы такую функцию, если б не знали о сопоставлении с образцом:
addVectors:: (Double, Double) -> (Double, Double) -> (Double, Double) addVectors a b = (fst a + fst b, snd a + snd b) Это, конечно, сработает, но есть способ лучше. Давайте испра- вим функцию, чтобы она использовала сопоставление с образцом: addVectors:: (Double, Double) -> (Double, Double) -> (Double, Double) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) Так гораздо лучше. Теперь ясно, что параметры функции яв- ляются кортежами; к тому же компонентам кортежа сразу даны имена – это повышает читабельность. Заметьте, что мы сразу напи- сали образец, соответствующий любым значениям. Тип функции addVectors в обоих случаях совпадает, так что мы гарантированно получим на входе две пары: ghci>:t addVectors addVectors:: (Double, Double) -> (Double, Double) -> (Double, Double) Функции fst и snd извлекают компоненты пары. Но как быть с тройками? Увы, стандартных функций для этой цели не сущест- вует, однако мы можем создать свои: first:: (a, b, c) –> a first (x, _, _) = x second:: (a, b, c) –> b second (_, y, _) = y third:: (a, b, c) –> c third (_, _, z) = z Символ _ имеет то же значение, что и в генераторах списков. Он означает, что нам не интересно значение на этом месте, так что мы просто пишем _.
|
|||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2017-02-17; просмотров: 215; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.129.210.36 (0.006 с.) |