Ответ 1
Конечно, это:
number_of_elements = (length .) . filter
Я хочу определить функцию, которая вычисляет количество элементов в списке, которые удовлетворяют заданному предикату:
number_of_elements :: (a -> Bool) -> [a] -> Int
number_of_elements f xs = length (filter f xs)
Например:
number_of_elements (==2) [2,1,54,1,2]
должен вернуть 2.
Мы можем записать его короче:
number_of_elements f = length . filter f
Можно ли записать его без параметра f?
Конечно, это:
number_of_elements = (length .) . filter
Я не думаю, что вы можете стать более читабельным, чем то, что вы предложили. Однако, просто для удовольствия вы можете это сделать:
numberOfElements = (.) (.) (.) length filter
или
(.:) = (.) . (.)
numberOfElements = length .: filter
Вам может понравиться читать Комбинаторы семантического редактора. Возьмите комбинатор result
оттуда:
result :: (output -> output') -> (input -> output) -> (input -> output')
result = (.)
Комбинатор result
принимает функцию и применяет ее к результату другой функции. Теперь, глядя на функции, которые у нас есть:
filter :: (a -> Bool) -> [a] -> [a]
length :: [a] -> Int
Теперь length
применяется к [a]
; который, оказывается, является результатом типа функций вида foo :: [a] -> [a]
. Таким образом,
result length :: ([a] -> [a]) -> ([a] -> Int)
Но результат filter
- это точно функция [a] -> [a]
, поэтому мы хотим применить result length
к результату filter
:
number_of_elements = result (result length) filter