Это второй ответ, и существующий отличный, поэтому я покажу свой альтернативный вариант; в конце концов, два объяснения не могут быть хуже одного, верно?
То, что filter
ожидает от вас, - это функция, которая скажет ему одно - следует ли мне сохранить данный элемент в полученном collection?
Тип этой функции - (a -> Bool)
, и это то, что мы называем предикатом .
В вашем конкретном случае c, предполагая
type SongEntry = (SongName, SongArtist, SaleQty)
Это будет функция типа SongEntry -> Bool
. Таких функций может быть много ... может быть, вам нужно больше 100 продаж?
hasMoreThan100Sales :: SongEntry -> Bool
hasMoreThan100Sales (_, _, sales) = sales > 100
Чтобы использовать:
filter hasMoreThan100Sales songs
Это должно быть достаточно просто. Что, если бы нам нужно было больше n
продаж? Вот где действительно сияет карри Haskell по умолчанию. Мы можем добавить один дополнительный параметр:
hasMoreThanNSales :: Int -> SongEntry -> Bool
, который мы также можем читать и понимать как Int -> (SongEntry -> Bool)
. Реализация на данном этапе проста:
hasMoreThanNSales n (_, _, sales) = sales > n
И что очень важно, чтобы получить нашу предыдущую функцию «100», нам просто нужно ее применить:
hasMoreThanNSales 100 :: SongEntry -> Bool
Это имеет тип, который мы необходимо использовать его с filter
:
filter (hasMoreThanNSales 100) songs
На этом этапе вы должны понять это достаточно хорошо, чтобы написать свой собственный предикат, который можно параметризовать любым удобным для вас способом.
О, и еще одна вещь, которая может сбивать с толку. hasMoreThan100Sales
- это предикат. hasMoreThanNSales
не , пока вы не примените его со значением (например, 100) - (hasMoreThanNSales 100)
является предикатом.