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

Эта функция используется при чтении конфигурационных файлов. Если есть уверенность в том, что файл

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

то мы можем считать, что его значение окажется неизменным на протяжении работы программы. Это говорит

о том, что нам не важно когда читать данные. Поэтому здесь мы вроде бы ничем не рискуем. “Вроде бы”

потому что ответственность за постоянство файла лежит на наших плечах.

Эта функция часто используется при вызове функций С через Haskell. В Haskell есть возможность вызывать

функции, написанные на C. Но по умолчанию такие функции заворачиваются в тип IO. Если функция является

чистой в С, то она будет чистой и при вызове через Haskell. Мы можем поручиться за её чистоту и вычислитель

нам поверит. Но если мы его обманули, мы пожнём плоды своего обмана.

138 | Глава 8: IO

Отладка программ

Раз уж речь зашла о “грязных” возможностях языка стоит упомянуть функцию trace из модуля

Debug.Trace. Посмотрим на её тип:

trace :: String -> a -> a

Это служебная функция эхо-печати. Когда дело доходит до вычисления функции trace на экран выводит-

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

Это функция id с побочным эффектом вывода сообщения на экран. Ею можно пользоваться для отладки. На-

пример так можно вернуть значение и распечатать его:

echo :: Show a => a -> a

echo a = trace (show a) a

8.6 Композиция монад

Эта глава завершает наше путешествие в мире типов-монад. Мы начали наше знакомство с монадами с

композиции, мы определили класс Monad через класс Kleisli, который упрощал составление специальных

функций вида a -> m b. Тогда мы познакомились с самыми простыми типами монадами (списки и частично

определённые функции), потом мы перешли к типам посложнее, мы научились проводить вычисления с

состоянием. В этой главе мы рассмотрели самый важный тип монаду IO. Мне бы хотелось замкнуть этот

рассказ на теме композиции. Мы поговорим о композиции нескольких монад.

Если вы посмотрите в исходный код библиотеки transformers, то увидите совсем другое определение для

State:

type State s = StateT s Identity

newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }

newtype Identity a = Identity { runIdentity :: a }

Но так ли оно далеко от нашего? Давайте разберёмся. Identity это тривиальный тип обёртка. Мы просто

заворачиваем значение в конструктор и ничего с ним не делаем. Вы наверняка сможете догадаться как опре-

делить экземпляры всех рассмотренных в этой главе классов для этого типа. Тип StateT больше похож на

наше определение для State, единственное отличие – это дополнительный параметр m в который завёрнут

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

в определении для State

type State s = StateT s Identity

Мы передаём дополнительным параметром в StateT тип Identity, который как раз ничего и не делает

с типом. Так мы получим наше исходное определение, но зачем такие премудрости? Такой тип принято

называть монадным трансформером (monad transformer). Он определяет композицию из нескольких монад в

данном случае одной из монад является State. Посмотрим на экземпляр класса Monad для StateT

instance (Monad m) => Monad (StateT s m) where

return a = StateT $ \s -> return (s, a)

a >>= f = StateT $ \s0 ->

runStateT a s0 >>= \(b, s1) -> runStateT (f b) s1

В этом определении мы пропускаем состояние через сито методов класса Monad для типа m. В остальном

это определение ничем не отличается от нашего. Также определены и ReaderT, WriterT, ListT и MaybeT.

Ключевым классом для всех этих типов является класс MonadTrans:

class MonadTrans t where

lift :: Monad m => m a -> t m a

Этот тип позволяет нам заворачивать специальные значения типа m в значения типа t. Посмотрим на

определение для StateT:

instance MonadTrans (StateT s) where

lift m = StateT $ \s -> liftM (,s) m

Композиция монад | 139

Напомню, что функция liftM это тоже самое , что и функция fmap, только она определена через методы

класса Monad. Мы создали функцию обновлнения состояния, которая ничего не делает с состоянием, а лишь

прицепляет его к значению.

Приведём простой пример применения трансформеров. Вернёмся к примеру FSM из предыдущей главы.

Предположим, что наш конечный автомат не только реагирует на действия, но и ведёт журнал, в который

записываются все поступающие на вход события. За переход состояний будет по прежнему отвечать тип State

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

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

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

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

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

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

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

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

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

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

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