Bool
образует ограниченную решетку *, где False
- это снизу , а True
- сверху . Эта ограниченная решетка определяет (полное) упорядочение, где False
действительно строго меньше, чем True
. (Они также являются единственными элементами этой решетки.)
Булевы операции and
и or
также могут рассматриваться как , встречаются и , соединяются , соответственно в этой решетке. Meet находит наибольшую нижнюю границу, а join находит наименьшую верхнюю границу. Это означает, что a && False = False
- это то же самое, что сказать, что нижняя граница дна и всего остального является нижней, а a || True = True
- это то же самое, что сказать, что верхняя граница вершины и всего остального является верхней. Так что meet и join, которые используют свойство ordering логических значений, эквивалентны логическим операциям, с которыми вы знакомы.
Вы можете использовать min
и max
, чтобы показать это в Haskell:
False `min` True = False -- this is the greatest lower bound
False && True = False -- so is this
False `max` True = True -- this is the least upper bound
False || True = True -- so is this
Это показывает, что вы можете определить &&
и ||
только из Производный Ord
экземпляр:
(&&) = min
(||) = max
Обратите внимание, что эти определения не эквивалентны при наличии другого вида дна , потому что (&&)
и (||)
являются короткозамкнутыми ( не является строгим во втором аргументе, когда первым является False
или True
, соответственно), в то время как min
и max
нет.
Также, небольшое исправление: предложение deriving
не говорит о том, что Bool
«происходит от» Ord
. Он инструктирует GHC получить экземпляр класса типов Ord
для типа Bool
.
* Более конкретно, дополняется распределительная решетка . Точнее говоря, булева алгебра .
Это потому, что дизайнеры Haskell ошиблись! Я никогда не видел учебник по математике, в котором упоминается порядок логических значений. Просто потому, что они могут быть, это не значит, что следует. Некоторые из нас используют Haskell именно потому, что во многих случаях он запрещает / защищает нас от смущающих / бессмысленных вещей, но не в этом.
instance Ord Bool
заставляет a => b
означать то, что вы ожидаете, что a <= b
будет означать!
Более ранние аргументы в пользу instance Ord Bool
, где вы можете сделать больше типов неявно сопоставимыми. Продолжая эту линию аргументации, некоторые, возможно, захотят сделать все типы сопоставимыми неявно и даже иметь слабую динамическую типизацию и вообще пропустить классы типов. Но мы хотим, чтобы строгая типизация в точности запрещала то, что явно не правильно, и instance Ord Bool
побеждает эту цель.
Что касается аргумента, что Bool является ограниченной решеткой. В отличие от boolean: = {True, False}, в Haskell мы имеем Bool: = {True, False, bottom} больше не является ограниченной решеткой, поскольку ни True, ни False не являются элементами идентичности в представлении bottom. Это связано с обсуждением комментариев & amp; & amp; против мин и т. д.
Экземпляр Ord
для Bool
становится гораздо важнее, когда вам нужно сравнить значения, которые содержат Bool
где-то внутри. Например, без него мы не смогли бы написать такие выражения, как:
[False,True] `compare` [False,True,False]
(3, False) < (3, True)
data Person = Person { name :: String, member :: Bool } deriving (Eq, Ord)
и т. Д.