Изучай Haskell во имя добра! (Липовача) - страница 210

Когда мы объединяем значения типа >All с помощью функции >mappend, результатом будет >True только в случае, если все значения, использованные в функции >mappend, равны >True:

>ghci> getAll $ mempty `mappend` All True

>True

>ghci> getAll $ mempty `mappend` All False

>False

>ghci> getAll . mconcat . map All $ [True, True, True]

>True

>ghci> getAll . mconcat . map All $ [True, True, False]

>False

Так же, как при использовании умножения и сложения, мы обычно явно указываем бинарные функции вместо оборачивания их в значения >newtype и последующего использования функций >mappend и >mempty. Функция >mconcat кажется полезной для типов >Any и >All, но обычно проще использовать функции >or и >and. Функция >or принимает списки значений типа >Bool и возвращает >True, если какое-либо из них равно >True. Функция >and принимает те же значения и возвращает значение >True, если все из них равны >True.

Моноид Ordering

Помните тип >Ordering? Он используется в качестве результата при сравнении сущностей и может иметь три значения: >LT, >EQ и >GT, которые соответственно означают «меньше, чем», «равно» и «больше, чем».

>ghci> 1 `compare` 2

>LT

>ghci> 2 `compare` 2

>EQ

>ghci> 3 `compare` 2

>GT

При использовании чисел и значений типа >Bool поиск моноидов сводился к просмотру уже существующих широко применяемых функций и их проверке на предмет того, проявляют ли они какое-либо поведение, присущее моноидам. При использовании типа >Ordering нам придётся приложить больше старания, чтобы распознать моноид. Оказывается, его экземпляр класса >Monoid настолько же интуитивен, насколько и предыдущие, которые мы уже встречали, и кроме того, весьма полезен:

>instance Monoid Ordering where

>   mempty = EQ

>   LT `mappend` _ = LT

>   EQ `mappend` y = y

>   GT `mappend` _ = GT

Экземпляр определяется следующим образом: когда мы объединяем два значения типа >Ordering с помощью функции >mappend, сохраняется значение слева, если значение слева не равно >EQ. Если значение слева равно >EQ, результатом будет значение справа. Единичным значением является >EQ. На первый взгляд, такой выбор может показаться несколько случайным, но на самом деле он имеет сходство с тем, как мы сравниваем слова в алфавитном порядке. Мы смотрим на первые две буквы, и, если они отличаются, уже можем решить, какое слово шло бы первым в словаре. Если же первые буквы равны, то мы переходим к сравнению следующей пары букв, повторяя процесс[13].



Например, сравнивая слова «ox» и «on», мы видим, что первые две буквы каждого слова равны, а затем продолжаем сравнивать вторые буквы. Поскольку «x» в алфавите идёт после «