Прежде чем я объясню эту последнюю строку кода, позвольте мне кратко описать процесс решения этого типа проблемы. Есть два ключевых вопроса:
- Какой самый простой случай?
- Могу ли я выразить решение через следующее простейшее решение?
ОК, поэтому мы хотим написать функцию, которая вычисляет произведение всех чисел в списке.
По вопросу 1. Самый простой возможный случай: чисел нет. Если я впервые столкнулся с проблемой, для меня может быть неясно, каким должен быть ответ в этом случае, но давайте пока отложим это.
По вопросу 2. Если у меня есть список [n0, n1, n2, .. nk], и я каким-то образом знаю произведение (назовем его p) всех чисел, кроме первого, тогда ответ первый элемент умножить на это произведение, или n0 * p.
Первая строка кода позаботится о тривиальном случае:
productIt [] = 1
Это говорит о том, что функция productIt для аргумента пустого списка, [], имеет значение 1. (Я объяснил выше, почему ответ должен быть 1.) Это решает тривиальный случай. Теперь нам нужно определить productIt в случае, если список не пустой. Давайте посмотрим на эту последнюю строку кода:
productIt (x:xs) = ... something?
Левая сторона использует сопоставление с образцом. Шаблон (x: xs) будет соответствовать списку с одним или несколькими элементами. Когда это выражение совпадает, оно связывает x с первым элементом, а xs с остальной частью списка. Таким образом, мы не только сопоставляем шаблон, мы получаем x и xs, определенные как бонус. Вот что делает сопоставление с образцом действительно мощным в Haskell.
Итак, если первый элемент списка - x, а остальная часть списка (все, кроме первого элемента) - xs, то каков ответ? Мы уже решили, что это первый элемент (x), умноженный на произведение всех остальных элементов (xs). Итак ...
productIt (x:xs) = x * productIt xs
Кроме того, yjerem дал вам превосходное объяснение того, как Haskell оценит это.