и
>badGreeting
, например:
>badGreeting :: String
>badGreeting = "О, чёрт, это ты,"
>niceGreeting :: String
>niceGreeting = "Привет! Так приятно тебя увидеть,"
>greet :: String -> String
>greet "Хуан" = niceGreeting ++ " Хуан!"
>greet "Фернандо" = niceGreeting ++ " Фернандо!"
>greet name = badGreeting ++ " " ++ name
Сопоставление с образцами в секции where
Можно использовать привязки в секции >where
и для сопоставления с образцом. Перепишем секцию >where
в нашей функции так:
> ...
> where bmi = weight / height 2
> (skinny, normal, fat) = (18.5, 25.0, 30.0)
Давайте создадим ещё одну простую функцию, которая принимает два аргумента: имя и фамилию, и возвращает инициалы.
>initials :: String –> String –> String
>initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
> where (f:_) = firstname
> (l:_) = lastname
Можно было бы выполнять сопоставление с образцом прямо в параметрах функции (это проще и понятнее), но мы хотим показать, что это допускается сделать и в определениях после ключевого слова >where
.
Точно так же, как мы определяли константы в секции >where
, можно определять и функции. Придерживаясь нашей темы «здорового» программирования, создадим функцию, которая принимает список из пар «вес–рост» и возвращает список из ИМТ.
>calcBmis :: [(Double, Double)] –> [Double]
>calcBmis xs = [bmi w h | (w, h) <– xs]
> where bmi weight height = weight / height 2
Видите, что происходит? Причина, по которой нам пришлось представить >bmi
в виде функции в данном примере, заключается в том, что мы не можем просто вычислить один ИМТ для параметров, переданных в функцию. Нам необходимо пройтись по всему списку и для каждой пары вычислить ИМТ.
Определения, заданные с помощью ключевого слова >let
, очень похожи на определения в секциях >where
. Ключевое слово >where
– это синтаксическая конструкция, которая позволяет вам связывать выражения с переменными в конце функции; объявленные переменные видны во всём теле функции, включая сторожевые условия. Ключевое же слово >let
позволяет связывать выражения с именами в любом месте функции; конструкции >let
сами по себе являются выражениями, но их область видимости ограничена локальным контекстом. Таким образом, определение >let
, сделанное в охранном выражении, видно только в нём самом.
Как и любые другие конструкции языка Haskell, которые используются для привязывания имён к значениям, определения >let
могут быть использованы в сопоставлении с образцом. Посмотрим на них в действии! Вот как мы могли бы определить функцию, которая вычисляет площадь поверхности цилиндра по высоте и радиусу: