Читаем Учебник по Haskell полностью

значение, то оно подставляется в следующую частично определённую функцию. Если же первая функция не

смогла вычислить результат и вернула Nothing, то считается что вся функция (f*> g) вернула Nothing.

Теперь давайте закодируем это определение в Haskell. При этом мы воспользуемся нашим классом

Kleisli. Аналогом функции id для частично определённых функций будет функция, которая просто за-

ворачивает значение в конструктор Just.

instance Kleisli Maybe where

idK

= Just

f *> g = \a -> case f a of

Nothing -> Nothing

Just b

-> g b

Смотрите, в case-выражении мы возвращаем Nothing, если функция f вернула Nothing, а если ей удалось

вычислить значение и она вернула (Just b) мы передаём это значение в следующую функцию, то есть

составляем выражение (g b).

Сохраним это определение в модуле Kleisli, а также определение для функции pred и загрузим модуль

в интерпретатор. Перед этим нам придётся добавить в список функций, которые мы не хотим импортировать

из Prelude функцию pred, она также уже определена в Prelude. Для определения нашей функции нам по-

требуется модуль Nat, который мы уже определили. Скопируем файл Nat. hs в ту же директорию, в которой

содержится файл Kleisli. hs и подключим этот модуль. Шапка модуля примет вид:

Примеры специальных функций | 89

a

f

b

b

g

c

Nothing

Nothing

b

a

g

f

c

Nothing

a

f*>g

c

Nothing

Рис. 6.3: Композиция частично определённых функций

module Kleisli where

import Prelude hiding(id, (>> ), pred)

import Nat

Добавим определение экземпляра Kleisli для Maybe в модуль Kleisli а также определение функции

pred. Сохраним обновлённый модуль и загрузим в интерпретатор.

*Kleisli> :load Kleisli

[1 of 2] Compiling Nat

( Nat. hs, interpreted )

[2 of 2] Compiling Kleisli

( Kleisli. hs, interpreted )

Ok, modules loaded: Kleisli, Nat.

*Kleisli> let pred2 = pred *> pred

*Kleisli> let pred3 = pred *> pred *> pred

*Kleisli> let two

= Succ (Succ Zero)

*Kleisli>

*Kleisli> pred two

Just (Succ Zero)

*Kleisli> pred3 two

Nothing

Обратите внимание на то, как легко определяются производные функции. Желаемое поведение для ча-

стично определённых функций закодировано в функции (*> ) теперь нам не нужно заворачивать значения и

разворачивать их из типа Maybe.

Приведём пример функции, которая составлена из частично определённой функции и обычной. Опреде-

лим функцию beside, которая вычисляет соседей для данного числа Пеано.

*Kleisli> let beside = pred +> \a -> (a, a + 2)

*Kleisli> beside Zero

Nothing

*Kleisli> beside two

Just (Succ Zero, Succ (Succ (Succ Zero)))

*Kleisli> (pred *> beside) two

Just (Zero, Succ (Succ Zero))

В выражении

pred +> \a -> (a, a + 2)

Мы сначала вычисляем предыдущее число, и если оно есть составляем пару из \a -> (a, a+2), в пару

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

число в итоговом кортеже окажется предыдущее число и следующее.

90 | Глава 6: Функторы и монады: теория

Итак с помощью функций из класса Kleisli мы можем составлять частично определённые функции в

бесточечном стиле. Обратите внимание на то, что все функции кроме pred были составлены в интерпрета-

торе.Отметим, что в Prelude определена специальная функция maybe, которая похожа на функцию foldr для

списков, она заменяет в значении типа Maybe конструкторы на функции. Посмотрим на её определение:

maybe

:: b -> (a -> b) -> Maybe a -> b

maybe n f Nothing

=

n

maybe n f (Just x) =

f x

С помощью этой функции мы можем переписать определение экземпляра Kleisli так:

instance Kleisli Maybe where

idM

= Just

f *> g

= f >> maybe Nothing g

Многозначные функции

Многозначные функции ветрены и непостоянны. Для некоторых значений аргументов они возвращают

одно значение, для иных десять, а для третьих и вовсе ничего. В Haskell такие функции имеют тип a -> [b].

Функция возвращает список ответов. На (рис. 6.4) изображена схема многозначной функции.

a

f

b

Рис. 6.4: Многозначная функция

Приведём пример. Системы Линденмайера (или L-системы) моделируют развитие живого организма.

Считается, что организм состоит из последовательности букв (или клеток). В каждый момент времени одна

буква заменяется на новую последовательность букв, согласно определённым правилам. Так организм живёт

и развивается. Приведём пример:

a → ab

b → a

a

ab

aba

abaab

abaababa

У нас есть два правила размножения клеток-букв в организме. На каждом этапе мы во всём слове заме-

няем букву a на слово ab и букву b на a. Начав с одной буквы a, мы за несколько шагов пришли к более

сложному слову.

Опишем этот процесс в Haskell. Для этого определим правила развития организма в виде многозначной

функции:

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных