Учебник по Haskell - [32]

Шрифт
Интервал

определим знакомую функцию равенства для Nat:

instance Eq Nat where

(==) a b =

case (a, b) of

(Zero,

Zero)

-> True

(Succ a’, Succ b’)

-> a’ == b’

_

-> False

Мы проводим сопоставление с образцом по кортежу (a, b), соответственно слева от знака -> мы прове-

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

Давайте определим функцию filter в ещё более композиционном стиле. Для этого мы заменим в исход-

ном определении where на let и декомпозицию в аргументах на case-выражение:

filter :: (a -> Bool) -> [a] -> [a]

filter

p

a =

case a of

[]

-> []

x:xs

->

let rest = filter p xs

in

if (p x)

then (x:rest)

else rest

4.3 Условные выражения

С условными выражениями мы уже сталкивались в сопоставлении с образцом. Например в определении

функции not:

not True

= False

not False = True

В зависимости от поступающего значения мы выбираем одну из двух альтернатив. Условные выражении

в сопоставлении с образцом позволяют реагировать лишь на частичное (с учётом переменных) совпадение

дерева значения в аргументах функции.

Часто нам хочется определить более сложные условия для альтернатив. Например, если значение на

входе функции больше 2, но меньше 10, верни A, а если больше 10, верни B, а во всех остальных случаях

верни C. Или если на вход поступила строка состоящая только из букв латинского алфавита, верни A, а

в противном случае верни B. Нам бы хотелось реагировать лишь в том случае, если значение некоторого

типа a удовлетворяет некоторому предикату. Предикатами обычно называют функции типа a -> Bool. Мы

говорим, что значение удовлетворяет предикату, если предикат для этого значения возвращает True.

62 | Глава 4: Декларативный и композиционный стиль

Охранные выражения

В декларативном стиле условные выражения представлены охранными выражениями (guards). Предполо-

жим у нас есть тип:

data HowMany = Little | Enough | Many

И мы хотим написать функцию, которая принимает число людей, которые хотят посетить выставку, а

возвращает значение типа HowMany. Эта функция оценивает вместительность выставочного зала. С помощью

охранных выражений мы можем написать её так:

hallCapacity :: Int -> HowMany

hallCapacity n

| n < 10

= Little

| n < 30

= Enough

| True

= Many

Специальный символ | уже встречался нам в определении типов. Там он играл роль разделителя аль-

тернатив в сумме типов. Здесь же он разделяет альтернативы в условных выражениях. Сначала мы пишем

| затем выражение-предикат, которое возвращает значение типа Bool, затем равно и после равно – возвра-

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

вниз, до тех пор пока в одной из альтернатив предикат не вернёт значение True. Обратите внимание на то,

что нам не нужно писать во второй альтернативе:

| 10 <= n && n < 30

= Enough

Если вычислитель дошёл до этой альтернативы, значит значение точно больше либо равно 10. Поскольку

в предыдущей альтернативе предикат вернул False.

Предикат в последней альтернативе является константой True, он пройдёт сопоставление с любым зна-

чением n. В данном случае, если учесть предыдущие альтернативы мы знаем, что если вычислитель дошёл

до последней альтернативы , значение n больше либо равно 30. Для повышения наглядности кода в Prelude

определена специальная константа-синоним значению True под именем otherwise.

Определим функцию filter для списков в более декларативном стиле, для этого заменим if-выражение

в исходной версии на охранные выражения:

filter :: (a -> Bool) -> [a] -> [a]

filter

p

[]

= []

filter

p

(x:xs)

| p x

= x : rest

| otherwise

= rest

where rest = filter p xs

Или мы можем разместить охранные выражения по-другому:

filter :: (a -> Bool) -> [a] -> [a]

filter

p

[]

= []

filter

p

(x:xs)

| p x

= x : rest

| otherwise = rest

where rest = filter p xs

Отметим то, что локальная переменная rest видна и в той и в другой альтернативе. Вы спокойно можете

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

Определим с помощью охранных выражений функцию all, она принимает предикат и список, и проверяет

удовлетворяют ли все элементы списка данному предикату.

all :: (a -> Bool) -> [a] -> Bool

all p []

= True

all p (x:xs)

| p x

= all p xs

| otherwise = False

С помощью охранных выражений можно очень наглядно описывать условные выражения. Но иногда мож-

но обойтись и простыми логическими операциями. Например функцию all можно было бы определить так:

Условные выражения | 63

all :: (a -> Bool) -> [a] -> Bool

all

p

[]

= True

all

p

(x:xs)

= p x && all p xs

Или так:

all :: (a -> Bool) -> [a] -> Bool

all

p

xs = null (filter notP xs)

where notP x = not (p x)

Или даже так:

import Prelude(all)

Функция null определена в Prelude она возвращает True только если список пуст.

if-выражения

В композиционном стиле в качестве условных выражений используются уже знакомые нам if-выражения.

Вспомним как они выглядят:

a = if bool

then x1

else x2

Слова if, then и else – ключевые. Тип a, x1 и x2 совпадают.

Любое охранное выражение, в котором больше одной альтернативы, можно представить в виде if-

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

hallCapacity


Рекомендуем почитать
Уголовное право. Особенная часть

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


Уголовно-исполнительное право

В книге кратко изложены ответы на основные вопросы темы «Уголовно-исполнительное право». Издание поможет систематизировать знания, полученные на лекциях и семинарах, подготовиться к сдаче экзамена или зачета.Пособие адресовано студентам высших и средних образовательных учреждений, а также всем интересующимся данной тематикой.


Самоучитель Adobe Premiere 6.5

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


Финансовое право

В учебном пособии в краткой и доступной форме рассмотрены все основные вопросы, предусмотренные государственным образовательным стандартом и учебной программой по дисциплине «Финансовое право».Книга позволит быстро получить основные знания по предмету, а также качественно подготовиться к зачету и экзамену.Рекомендуется студентам, аспирантам и преподавателям по юридическим, экономическим и управленческим специальностям, а также сотрудникам банков.Автор книги, Шевчук Денис Александрович, имеет опыт преподавания различных дисциплин в ведущих ВУЗах Москвы (экономические, юридические, технические, гуманитарные), два высших образования (экономическое и юридическое), более 30 публикаций (статьи и книги), Член Союза Юристов Москвы, Член Союза Журналистов России, Член Союза Журналистов Москвы, Стипендиат Правительства РФ, опыт работы в банках, коммерческих и государственных структурах (в т.ч.


фгос  ответы

Содержащиеся в пособии контрольно-измерительные материалы (КИМы) для 5 класса, аналогичные материалам ЕГЭ, составлены в соответствии с программой общеобразовательных учреждений по русскому языку и учитывают возрастные особенности учащихся. В конце пособия даны ответы на все варианты тестов, предложены диктанты различных типов.Пособие адресовано учителям, ученикам, их родителям и всем, кому необходимо закрепить и систематизировать знания перед ЕГЭ.


Теория литературы. Чтение как творчество

Цель предлагаемого пособия – систематизировать и обогатить представления о природе, структуре и особенностях художественной литературы как вида искусства, помочь совершенствованию читательского мастерства. Книга снабжена кратким словарем основных литературоведческих понятий и терминов (составлен при участии доцента О.В. Быстровой).Для студентов филологических факультетов, учителей, преподавателей литературы высших и средних учебных заведений.