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

Этот класс является классом Category в мире наших специальных функций. Если мы сотрём все буквы m,

то мы получим обычные типы для тождества и композиции. В этом мире должны выполняться те же правила:

f

*> idK

== f

idK *> f

== f

f *> (g *> h) == (f *> g) *> h

Взаимодействие с внешним миром

С помощью класса Kleisli мы можем составлять из одних специальных функций другие. Но как мы

сможем комбинировать специальные функции с обычными?

Поскольку слева у нашей специальной функции обычный общий тип, то с этой стороны мы можем вос-

пользоваться обычной функцией композиции >> . Но как быть при композиции справа? Нам нужна функция

типа:

(a -> m b) -> (b -> c) -> (a -> m c)

Оказывается мы можем составить её из методов класса Kleisli. Мы назовём эту функцию композиции

(+> ).

(+> ) :: Kleisli m => (a -> m b) -> (b -> c) -> (a -> m c)

f +> g = f *> (g >> idK)

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

Композиция функций | 87

Три композиции

У нас появилось много композиций целых три:

аргументы

|

результат

обычная

>>

обычная

==

обычная

специальная

+>

обычная

==

специальная

специальная

*>

специальная

==

специальная

При этом важно понимать, что по смыслу это три одинаковые функции. Они обозначают операцию по-

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

Обобщённая формулировка категории Клейсли

Отметим, что мы могли бы сформулировать класс Kleisli и в более общем виде с помощью класса

Category:

class Kleisli m where

idK

:: Category cat => cat a (m a)

(*> ) :: Category cat => cat a (m b) -> cat b (m c) -> cat a (m c)

(+> ) :: (Category cat, Kleisli m)

=> cat a (m b) -> cat b c -> cat a (m c)

f +> g = f *> (g >> idK)

Мы заменили функциональный тип на его обобщение. Для наглядности мы будем пользоваться специ-

альной формулировкой со стрелочным типом.

Для этого мы определим модуль Kleisli. hs

module Kleisli where

import Prelude hiding (id, (>> ))

class Category cat where

id

:: cat a a

(>> ) :: cat a b -> cat b c -> cat a c

class Kleisli m where

idK

:: a -> m a

(*> ) :: (a -> m b) -> (b -> m c) -> (a -> m c)

(+> ) :: Kleisli m => (a -> m b) -> (b -> c) -> (a -> m c)

f +> g = f *> (g >> idK)

-- Экземпляр для функций

instance Category (-> ) where

id

= \x -> x

f >> g

= \x -> g (f x)

Мы не будем импортировать функцию id, а определим её в классе Category. Также в Prelude уже опре-

делена функция (>> ) мы спрячем её с помощью специальной директивы hiding для того, чтобы она нам не

мешалась. Далее мы будем дополнять этот модуль экземплярами класса Kleisli и примерами.

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

Частично определённые функции

Частично определённые функции – это такие функции, которые определены не для всех значений аргу-

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

Поскольку числа натуральные, то для нуля такого числа нет. Для описания этого поведения мы можем вос-

пользоваться специальным типом Maybe. Посмотрим на его определение:

data Maybe a = Nothing | Just a

deriving (Show, Eq, Ord)

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

a

f

b

Nothing

Рис. 6.2: Частично определённая функция

Частично определённая функция имеет тип a -> Maybe b (рис. 6.2), если всё в порядке и значение было

вычислено, она вернёт (Just a), а в случае ошибки будет возвращено значение Nothing. Теперь мы можем

определить нашу функцию так:

pred :: Nat -> Maybe Nat

pred Zero

= Nothing

pred (Succ a)

= Just a

Для Zero предыдущий элемент не определён .

Составляем функции вручную

Значение функции pred завёрнуто в упаковку Maybe, и для того чтобы воспользоваться им нам придётся

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

числа:

pred2 :: Nat -> Maybe Nat

pred2 x =

case pred x of

Just (Succ a) -> Just a

_

-> Nothing

Если мы захотим определить pred3, мы заменим pred в case-выражении на pred2. Вроде не такое уж и

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

стиля. Нам бы хотелось написать так:

pred2 :: Nat -> Maybe Nat

pred2 = pred >> pred

pred3 :: Nat -> Maybe Nat

pred3 = pred >> pred >> pred

Но компилятор этого не допустит.

Композиция

Для того чтобы понять как устроена композиция частично определённых функций изобразим её вычисле-

ние графически (рис. 6.3). Сверху изображены две частично определённых функции. Если функция f вернула

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

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

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

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

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

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

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

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

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