Учебник по Haskell | страница 68
noName, а стрелку на знак равно:
noName x = x + 1
Мы получили обычную функцию Haskell, с такими мы уже много раз встречались. Зачем специальный
синтаксис для определения безымянных функций? Ведь можно определить её в виде уравнений. К тому же
кому могут понадобиться безымянные функции? Ведь смысл функции в том, чтобы выделить определённый
шаблон поведения и затем ссылаться на него по имени функции.
Смысл безымянной функции в том, что ею, также как и любым другим элементом композиционного
стиля, можно пользоваться в любой части обычных выражений. С её помощью мы можем создавать функции
“на лету”. Предположим, что мы хотим профильтровать список чисел, мы хотим выбрать из них лишь те, что
меньше 10, но больше 2, и к тому же они должны быть чётными. Мы можем написать:
f :: [Int] -> [Int]
f = filter p
where p x = x > 2 && x < 10 && even x
При этом нам приходится давать какое-нибудь имя предикату, например p. С помощью безымянной функ-
ции мы могли бы написать так:
f :: [Int] -> [Int]
f = filter (\x -> x > 2 && x < 10 && even x)
Смотрите мы составили предикат сразу в аргументе функции filter. Выражение (\x -> x > 2 && x <
10 && even x) является обычным значением.
Возможно у вас появился вопрос, где аргумент функции? Где тот список по которому мы проводим филь-
трацию. Ответ на этот вопрос кроется в частичном применении. Давайте вычислим по правилу применения
тип функции filter:
f :: (a -> Bool) -> [a] -> [a],
x :: (Int -> Bool)
------------------------------------------------------
(f x) :: [Int] -> [Int]
После применения параметр a связывается с типом Int, поскольку при применении происходит сопостав-
ление более общего предиката a -> Bool из функции filter с тем, который мы передали первым аргументом
Int -> Bool. После этого мы получаем тип (f x) :: [Int] -> [Int] это как раз тип функции, которая прини-
мает список целых чисел и возвращает список целых чисел. Частичное применение позволяет нам не писать
в таких выражениях:
f xs = filter p xs
where p x = ...
последний аргумент xs.
К примеру вместо
Определение функций | 65
add a b = (+) a b
мы можем просто написать:
add = (+)
Такой стиль определения функций называют бесточечным (point-free).
Давайте выразим функцию filter с помощью лямбда-функций:
filter :: (a -> Bool) -> ([a] -> [a])
filter = \p -> \xs -> case xs of
[]
-> []
(x:xs) -> let rest = filter p xs
in
if
p x
then x : rest
else rest
Мы определили функцию filter пользуясь только элементами композиционного стиля. Обратите внима-