Сравнение людей на равенство

Рассмотрим такой тип данных:

data Person = Person { firstName :: String

                     , lastName :: String

                     , age :: Int

                     }

Тип описывает человека. Предположим, что среди людей не встречаются тёзки одного возраста. Если у нас есть два описания, можем ли мы выяснить, относятся ли они к одному и тому же человеку? Есть ли в такой операции смысл? Конечно, есть. Мы можем сравнить записи и проверить, равны они или нет. Вот почему имело бы смысл определить для нашего типа экземпляр класса Eq. Порождаем экземпляр:

data Person = Person { firstName :: String

                     , lastName :: String

                     , age :: Int

                     } deriving (Eq)

Когда мы определяем экземпляр класса Eq для типа и пытаемся сравнить два значения с помощью операторов == или /=, язык Haskell проверяет, совпадают ли конструкторы значений (хотя в нашем типе только один конструктор), а затем проверяет все данные внутри конструктора на равенство, сравнивая каждую пару полей с помощью оператора ==. Таким образом, типы всех полей также должны иметь определённый экземпляр класса Eq. Так как типы полей нашего типа, String и Int, имеют экземпляры класса Eq, всё в порядке.

Запишем в файл несколько людей:

mikeD = Person {firstName = "Майкл", lastName = "Даймонд", age = 45}

adRock = Person {firstName = "Адам", lastName = "Горовиц", age = 45}

mca = Person {firstName = "Адам", lastName = "Яух", age = 47}

И проверим экземпляр класса Eq:

ghci> mca == adRock

False

ghci> mikeD == adRock

False

ghci> mikeD == mikeD

True

ghci> mca == Person {firstName = "Адам", lastName = "Яух", age = 47}

True

Конечно же, так как теперь тип Person имеет экземпляр класса Eq, мы можем передавать его любым функциям, которые содержат ограничение на класс типа Eq в декларации, например функции elem.

ghci> let beastieBoys = [mca, adRock, mikeD]

ghci> mikeD `elem` beastieBoys

True