Читаем Изучай Haskell во имя добра! полностью

Первые два закона утверждают, что значение mempty должно вести себя как единица по отношению к функции mappend, а третий говорит, что функция mappend должна быть ассоциативна (порядок, в котором мы используем функцию mappend для сведения нескольких моноидных значений в одно, не имеет значения). Язык Haskell не проверяет определяемые экземпляры на соответствие этим законам, поэтому мы должны быть внимательными, чтобы наши экземпляры действительно выполняли их.

<p>Познакомьтесь с некоторыми моноидами</p>

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

<p>Списки являются моноидами</p>

Да, списки являются моноидами! Как вы уже видели, функция ++ с пустым списком [] образуют моноид. Экземпляр очень прост:

instance Monoid [a] where

   mempty = []

   mappend = (++)

Для списков имеется экземпляр класса Monoid независимо от типа элементов, которые они содержат. Обратите внимание, что мы написали instance Monoid [a], а не instance Monoid [], поскольку класс Monoid требует конкретный тип для экземпляра.

При тестировании мы не встречаем сюрпризов:

ghci> [1,2,3] `mappend` [4,5,6]

[1,2,3,4,5,6]

ghci> ("один" `mappend` "два") `mappend` "три"

"одиндватри"

ghci> "один" `mappend` ("два" `mappend` "три")

"одиндватри"

ghci> "один" `mappend` "два" `mappend` "три"

"одиндватри"

ghci> "бах" `mappend` mempty

"бах"

ghci> mconcat [[1,2],[3,6],[9]]

[1,2,3,6,9]

ghci> mempty :: [a]

[]

Обратите внимание, что в последней строке мы написали явную аннотацию типа. Если бы было написано просто mempty, то интерпретатор GHCi не знал бы, какой экземпляр использовать, поэтому мы должны были сказать, что нам нужен списковый экземпляр. Мы могли использовать общий тип [a] (в отличие от указания [Int] или [String]), потому что пустой список может действовать так, будто он содержит любой тип.

Поскольку функция mconcat имеет реализацию по умолчанию, мы получаем её просто так, когда определяем экземпляр класса Monoid для какого-либо типа. В случае со списком функция mconcat соответствует просто функции concat. Она принимает список списков и «разглаживает» его, потому что это равнозначно вызову оператора ++ между всеми смежными списками, содержащимися в списке.

Законы моноидов действительно выполняются для экземпляра списка. Когда у нас есть несколько списков и мы объединяем их с помощью функции mappend (или ++), не имеет значения, какие списки мы соединяем первыми, поскольку так или иначе они соединяются на концах. Кроме того, пустой список действует как единица, поэтому всё хорошо.

Обратите внимание, что моноиды не требуют, чтобы результат выражения a `mappend` b был равен результату выражения b `mappend` a. В случае со списками они очевидно не равны:

ghci> "один" `mappend` "два"

"одиндва"

ghci> "два" `mappend` "один"

"дваодин"

И это нормально. Тот факт, что при умножении выражения 3 * 5 и 5 * 3 дают один и тот же результат, – это просто свойство умножения, но оно не выполняется для большинства моноидов.

<p>Типы Product и Sum</p>

Мы уже изучили один из способов рассматривать числа как моноиды: просто позволить бинарной функции быть оператором *, а единичному значению – быть 1. Ещё один способ для чисел быть моноидами состоит в том, чтобы в качестве бинарной функции выступал оператор +, а в качестве единичного значения – значение 0:

ghci> 0 + 4

4

ghci> 5 + 0

5

ghci> (1 + 3) + 5

9

ghci> 1 + (3 + 5)

9

Законы моноидов выполняются, потому что если вы прибавите 0 к любому числу, результатом будет то же самое число. Сложение также ассоциативно, поэтому здесь у нас нет никаких проблем.

Итак, в нашем распоряжении два одинаково правомерных способа для чисел быть моноидами. Какой же способ выбрать?.. Ладно, мы не обязаны выбирать! Вспомните, что когда имеется несколько способов определения для какого-то типа экземпляра одного и того же класса типов, мы можем обернуть этот тип в декларацию newtype, а затем сделать для нового типа экземпляр класса типов по-другому. Можно совместить несовместимое.

Модуль Data.Monoid экспортирует для этого два типа: Product и Sum.

Product определён вот так:

newtype Product a = Product { getProduct :: a }

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

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

1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

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

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

Финансы / Программирование, программы, базы данных
Язык программирования C++. Пятое издание
Язык программирования C++. Пятое издание

Лучшее руководство по программированию и справочник по языку, полностью пересмотренное и обновленное под стандарт С++11!Р'С‹ держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под стандарт С++11. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. Р' соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать РёС… наилучшие СЃРїРѕСЃРѕР±С‹ применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.Стенли Р'. Липпман работал старшим консультантом в Jet Propulsion Laboratory, архитектором РіСЂСѓРїРїС‹ Visual С++ корпорации Microsoft, техническим сотрудником Bell Laboratories и главным инженером- программистом по анимации в кинокомпаниях Disney, DreamWorks, Pixar и PDI.Р–РѕР·и Лажойе, работающий ныне в кинокомпании Pixar, был членом канадской РіСЂСѓРїРїС‹ разработчиков компилятора C/C++ корпорации IBM, а также возглавлял рабочую группу базового языка С++ в составе международной организации по стандартизации ANSI/ISO.Барбара Э. Му имеет почти тридцатилетний опыт программирования. На протяжении пятнадцати лет она работала в компании AT&T, сотрудничая с Бьярне Страуструпом, автором языка С++, и несколько лет руководила РіСЂСѓРїРїРѕР№ разработчиков С++.• Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования• Р

Барбара Э. Му , Жози Лажойе , Стенли Б. Липпман

Программирование, программы, базы данных
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Эта книга представляет собой перевод третьего издания американского бестселлера Effective C++ и является руководством по грамотному использованию языка C++. Она поможет сделать ваши программы более понятными, простыми в сопровождении и эффективными. Помимо материала, описывающего общую стратегию проектирования, книга включает в себя главы по программированию с применением шаблонов и по управлению ресурсами, а также множество советов, которые позволят усовершенствовать ваши программы и сделать работу более интересной и творческой. Книга также включает новый материал по принципам обработки исключений, паттернам проектирования и библиотечным средствам.Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Скотт Майерс , Скотт Мейерс

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