Количество элементов в Haskell в стиле без очков

Я хочу определить функцию, которая вычисляет количество элементов в списке, которые удовлетворяют заданному предикату:

  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?

Ответ 1

Конечно, это:

number_of_elements = (length .) . filter

Ответ 2

Я не думаю, что вы можете стать более читабельным, чем то, что вы предложили. Однако, просто для удовольствия вы можете это сделать:

numberOfElements = (.) (.) (.) length filter

или

(.:) = (.) . (.)
numberOfElements = length .: filter

Ответ 3

Вам может понравиться читать Комбинаторы семантического редактора. Возьмите комбинатор 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