Сравнение с образцом
Убрав слово if, мы и с нашими виртуальными «ИЛИ» можем расстаться. В этом случае останется лишь это:
analyzeGold :: Int -> String -- Одно объявление. -- И множество определений... analyzeGold 999 = "Wow! 999 standard!" analyzeGold 750 = "Great! 750 standard." analyzeGold 585 = "Not bad! 585 standard." analyzeGold _ = "I don't know such a standard..."
Мы просто перечислили определения функции analyzeGold одно за другим. На первый взгляд, возможность множества определений одной и той же функции удивляет, но если вспомнить, что применение функции суть выражение, тогда ничего удивительного. Вот как это читается:
analyzeGold 999 = "Wow! 999 standard!"
если эта функция применяется тогда этому выражению
к этому она аргументу равна
analyzeGold 750 = "Wow! 999 standard!"
если эта функция применяется тогда другому выражению
к другому она аргументу равна
...
analyzeGold _ = "I don't know such a standard..."
иначе эта функция равна общему выражению Когда функция analyzeGold применяется к конкретному аргументу, этот аргумент последовательно сравнивается с образцом (англ. pattern matching). Образца здесь три: 999, 750 и 585. И если раньше мы сравнивали аргумент с этими числовыми значениями явно, посредством функции ==, теперь это происходит скрыто. Идея сравнения с образцом очень проста: что-то (в данном случае реальный аргумент) сопоставляется с образцом (или образцами) на предмет «подходит/не подходит». Если подходит — то есть сравнение с образцом даёт результат True — готово, используем соответствующее выражение. Если же не подходит — переходим к следующему образцу.
Сравнение с образцом, называемое ещё «сопоставлением с образцом» используется в Haskell чрезвычайно широко. В русскоязычной литературе перевод словосочетания «pattern matching» не особо закрепился, вместо этого так и говорят «*шаблон матчинг». Я поступлю так же.
Но что это за символ подчёркивания такой, в последнем варианте определения? Вот этот:
analyzeGold _ = "I don't know such a standard..." ^
С формальной точки зрения, это — универсальный образец, сравнение с которым всегда истинно (ещё говорят, что с ним матчится (англ. match) всё что угодно). А с неформальной — это символ, который можно прочесть как «мне всё равно». Мы как бы говорим: «В данном случае нас не интересует конкретное содержимое аргумента, нам всё равно, мы просто возвращаем строку I don't know such a standard...».
Важно отметить, что сравнение аргумента с образцами происходит последовательно, сверху вниз. Поэтому если мы напишем так:
analyzeGold :: Int -> String analyzeGold _ = "I don't know such a standard..." analyzeGold 999 = "Wow! 999 standard!" analyzeGold 750 = "Great! 750 standard." analyzeGold 585 = "Not bad! 585 standard."
наша функция будет всегда возвращать первое выражение, строку I don't know such a standard..., и это вполне ожидаемо: первая же проверка гарантированно даст нам True, ведь с образцом _ совпадает всё что угодно. Таким образом, общий образец следует располагать в самом конце, чтобы мы попали на него лишь после того, как не сработали все остальные образцы.
- https://www.ohaskell.guide/choose-n-patterns.html Первоисточник