Количество элементов в Haskell в стиле pointfree - PullRequest
10 голосов
/ 24 декабря 2011

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

  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 ?

Ответы [ 3 ]

17 голосов
/ 24 декабря 2011

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

number_of_elements = (length .) . filter
12 голосов
/ 24 декабря 2011

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

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

или

(.:) = (.) . (.)
numberOfElements = length .: filter
7 голосов
/ 24 декабря 2011

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