Сопоставление с парами

Сопоставление с образцом может быть использовано и для кортежей. Что если мы хотим создать функцию, которая принимает два двумерных вектора (представленных в форме пары) и складывает их? Чтобы сложить два вектора, нужно сложить их соответствующие координаты. Вот как мы написали бы такую функцию, если б не знали о сопоставлении с образцом:

addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double)

addVectors a b = (fst a + fst b, snd a + snd b)

Это, конечно, сработает, но есть способ лучше. Давайте исправим функцию, чтобы она использовала сопоставление с образцом:

addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double)

addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

Так гораздо лучше. Теперь ясно, что параметры функции являются кортежами; к тому же компонентам кортежа сразу даны имена – это повышает читабельность. Заметьте, что мы сразу написали образец, соответствующий любым значениям. Тип функции addVectors в обоих случаях совпадает, так что мы гарантированно получим на входе две пары:

ghci> :t addVectors

addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double)

Функции fst и snd извлекают компоненты пары. Но как быть с тройками? Увы, стандартных функций для этой цели не существует, однако мы можем создать свои:

first :: (a, b, c) –> a

first (x, _, _) = x

second :: (a, b, c) –> b

second (_, y, _) = y

third :: (a, b, c) –> c

third (_, _, z) = z

Символ _ имеет то же значение, что и в генераторах списков. Он означает, что нам не интересно значение на этом месте, так что мы просто пишем _.