. Аналогичным образом оператор
>++
– это функция, которая принимает две сущности и возвращает третью. Но вместо того, чтобы перемножать числа, она принимает два списка и конкатенирует их. И так же, как оператор
>*
, она имеет определённое значение, которое не изменяет другое значение при использовании с оператором
>++
. Этим значением является пустой список:
>[]
.
>ghci> 4 * 1
>4
>ghci> 1 * 9
>9
>ghci> [1,2,3] ++ []
>[1,2,3]
>ghci> [] ++ [0.5, 2.5]
>[0.5,2.5]
Похоже, что оператор >*
вместе с >1
и оператор >++
наряду с >[]
разделяют некоторые общие свойства:
• функция принимает два параметра;
• параметры и возвращаемое значение имеют одинаковый тип;
• существует такое значение, которое не изменяет другие значения, когда используется с бинарной функцией.
Есть и ещё нечто общее между двумя этими операциями, хотя это может быть не столь очевидно, как наши предыдущие наблюдения. Когда у нас есть три и более значения и нам необходимо использовать бинарную функцию для превращения их в один результат, то порядок, в котором мы применяем бинарную функцию к значениям, неважен. Например, независимо от того, выполним ли мы >(3 * 4) * 5
или >3 * (4 * 5)
, результат будет равен >60
. То же справедливо и для оператора >++
:
>ghci> (3 * 2) * (8 * 5)
>240
>ghci> 3 * (2 * (8 * 5))
>240
>ghci> "ой" ++ ("лю" ++ "ли")
>"ойлюли"
>ghci> ("ой" ++ "лю") ++ "ли"
>"ойлюли"
Мы называем это свойство ассоциативностью. Оператор >*
ассоциативен, оператор >++
тоже. Однако оператор >–
, например, не ассоциативен, поскольку выражения >(5 – 3) – 4
и >5 – (3 – 4)
возвращают различные результаты.
Зная об этих свойствах, мы наконец-то наткнулись на моноиды!
Моноид состоит из ассоциативной бинарной функции и значения, которое действует как единица (единичное или нейтральное значение) по отношению к этой функции. Когда что-то действует как единица по отношению к функции, это означает, что при вызове с данной функцией и каким-то другим значением результат всегда равен этому другому значению. Значение >1
является единицей по отношению к оператору >*
, а значение >[]
является единицей по отношению к оператору >++
. В мире языка Haskell есть множество других моноидов, поэтому существует целый класс типов >Monoid
. Он предназначен для типов, которые могут действовать как моноиды. Давайте посмотрим, как определён этот класс типов:
>class Monoid m where
> mempty :: m
> mappend :: m –> m –> m mconcat :: [m] –> m
> mconcat = foldr mappend mempty
Класс типов >Monoid
определён в модуле >Data.Monoid
. Давайте потратим некоторое время, чтобы как следует с ним познакомиться.