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

внутри генератора списка, видны в функции вывода (часть до символа |) и для всех предикатов и секций, которые следуют после ключевого слова >let. Так что мы можем написать функцию, которая выводит только толстяков:

>calcBmis :: [(Double, Double)] -> [Double]

>calcBmis xs = [bmi | (w, h) <– xs, let bmi = w / h ^ 2, bmi > 25.0]

Использовать имя >bmi в части >(w, h) <– xs нельзя, потому что она расположена до ключевого слова >let.

Выражения let в GHCi

Часть >in также может быть пропущена при определении функций и констант напрямую в GHCi. В этом случае имена будут видимы во время одного сеанса работы GHCi.

>ghci> let zoot x y z = x * y + z

>ghci> zoot 3 9 2

>29

>ghci> let boot x y z = x * y + z in boot 3 4 2

>14

>ghci> boot

>:1:0: Not in scope: `boot'

Поскольку в первой строке мы опустили часть >in, GHCi знает, что в этой строке >zoot не используется, поэтому запомнит его до конца сеанса. Однако во втором выражении >let часть >in присутствует, и определённая в нём функция >boot тут же вызывается. Выражение >let, в котором сохранена часть >in, является выражением и представляет некоторое значение, так что GHCi именно это значение и печатает.

Выражения для выбора из вариантов


Во многих императивных языках (C, C++, Java, и т. д.) имеется оператор >case, и если вам доводилось программировать на них, вы знаете, что это такое. Вы берёте переменную и выполняете некую часть кода для каждого значения этой переменной – ну и, возможно, используете финальное условие, которое срабатывает, если не отработали другие.

Язык Haskell позаимствовал эту концепцию и усовершенствовал её. Само имя «выражения для выбора» указывает на то, что они являются… э-э-э… выражениями, так же как >if>then>else и >let. Мы не только можем вычислять выражения, основываясь на возможных значениях переменной, но и производить сопоставление с образцом.

Итак, берём переменную, выполняем сопоставление с образцом, выполняем участок кода в зависимости от полученного значения… где-то мы это уже слышали!.. Ах да, сопоставление с образцом по параметрам при объявлении функции! На самом деле это всего лишь навсего облегчённая запись для выражений выбора. Эти два фрагмента кода делают одно и то же – они взаимозаменяемы:

>head' :: [a] –> a

>head' [] = error "Никаких head для пустых списков!"

>head' (x:_) = x

>head' :: [a] –> a

>head' xs =

>  case xs of

>   [] –> error "Никаких head для пустых списков!"

>   (x:_) –> x

Как видите, синтаксис для выражений отбора довольно прост:

>case expression of

>  pattern –> result

>  pattern –> result

>  ...

Выражения проверяются на соответствие образцам. Сопоставление с образцом работает как обычно: используется первый образец, который подошёл. Если были опробованы все образцы и ни один не подошёл, генерируется ошибка времени выполнения.