Изучай Haskell во имя добра! (Липовача) - страница 32

>ghci> badAdd [100, 20]

>*** Exception: Non-exhaustive patterns in function badAdd

Это не так уж и хорошо. Если подобное случится в скомпилированной программе, то она просто вылетит.

И последнее замечание относительно сопоставления с образцами для списков: в образцах нельзя использовать операцию >++ (напомню, что это объединение двух списков). К примеру, если вы попытаетесь написать в образце >(xs++ys), то Haskell не сможет определить, что должно попасть в >xs, а что в >ys. Хотя и могут показаться логичными сопоставления типа >(xs++[x,y,z]) или даже >(xs ++ [x]), работать это не будет – такова природа списков[7].

Именованные образцы

Ещё одна конструкция называется именованным образцом. Это удобный способ разбить что-либо в соответствии с образцом и связать результат разбиения с переменными, но в то же время сохранить ссылку на исходные данные. Такую задачу можно выполнить, поместив некий идентификатор образца и символ >@ перед образцом, описывающим структуру данных. Например, так выглядит образец >xs@(x:y:ys).

Подобный образец работает так же, как (>x:y:ys), но вы легко можете получить исходный список по имени >xs, вместо того чтобы раз за разом печатать >x:y:ys в теле функции. Приведу пример:

>firstLetter :: String –> String

>firstLetter "" = "Упс, пустая строка!"

>firstLetter all@(x:xs) = "Первая буква строки " ++ all ++ " это " ++ [x]

Загрузим эту функцию и посмотрим, как она работает:

>ghci> firstLetter "Дракула"

>"Первая буква строки Дракула это Д"

Эй, стража!


В то время как образцы – это способ убедиться, что значение соответствует некоторой форме, и разобрать его на части, сторожевые условия (охрана, охранные выражения) – это способ проверить истинность некоторого свойства значения или нескольких значений, переданных функции. Тут можно провести аналогию с условным выражением >if: оно работает схожим образом. Однако охранные выражения гораздо легче читать, если у вас имеется несколько условий; к тому же они отлично работают с образцами.

Вместо того чтобы объяснять их синтаксис, давайте просто напишем функцию с использованием охранных условий. Эта простая функция будет оценивать вас на основе ИМТ (индекса массы тела). Ваш ИМТ равен вашему весу, разделённому на квадрат вашего роста.

Если ваш ИМТ меньше 18,5, можно считать вас тощим. Если ИМТ составляет от 18,5 до 25, ваш вес в пределах нормы. От 25 до 30 – вы полненький; более 30 – тучный. Запишем эту функцию (мы не будем рассчитывать ИМТ, функция принимает его как параметр и ругнёт вас соответственно).

>bmiTell :: Double -> String

>bmiTell bmi