Сопоставление с образцом может быть использовано и для кортежей. Что если мы хотим создать функцию, которая принимает два двумерных вектора (представленных в форме пары) и складывает их? Чтобы сложить два вектора, нужно сложить их соответствующие координаты. Вот как мы написали бы такую функцию, если б не знали о сопоставлении с образцом:
>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
Символ >_
имеет то же значение, что и в генераторах списков. Он означает, что нам не интересно значение на этом месте, так что мы просто пишем >_
.
Сопоставление со списками и генераторы списков
В генераторах списков тоже можно использовать сопоставление с образцом, например:
>ghci> let xs = [(1,3), (4,3), (2,4), (5,3), (5,6), (3,1)]
>ghci> [a+b | (a,b) <– xs]
>[4,7,6,8,11,4]
Если сопоставление с образцом закончится неудачей для одного элемента списка, просто произойдёт переход к следующему элементу.
Списки сами по себе (то есть заданные прямо в тексте образца списковые литералы) могут быть использованы при сопоставлении с образцом. Вы можете проводить сравнение с пустым списком или с любым образцом, который включает оператор >:
и пустой список. Так как выражение >[1,2,3]
– это просто упрощённая запись выражения >1:2:3:[]
, можно использовать >[1,2,3]
как образец.
Образец вида >(x:xs)
связывает «голову» списка с >x
, а оставшуюся часть – с >xs
, даже если в списке всего один элемент; в этом случае >xs
– пустой список.
ПРИМЕЧАНИЕ. Образец >(x:xs)
используется очень часто, особенно с рекурсивными функциями. Образцы, в определении которых присутствует