Использование фильтра, требующего множественного ввода - Haskell - PullRequest
2 голосов
/ 06 августа 2020

Я относительно новичок в Haskell и пытался изучить его в течение последних нескольких недель, но застрял на фильтрах и предикатах, которые я надеялся получить помощь в понимании.

Я столкнулся с проблемой, из-за которой у меня есть список кортежей. Каждый кортеж состоит из (songName, songArtist, saleQty), и от меня требуется удалить кортеж из этого списка на основе ввода пользователем songName и SongArtist.

При возврате результатов я понимаю, что могу удалить кортеж, используя Filter при возврате результатов. Я читал об этом с помощью LYAH. Это научило меня, что я должен использовать предикат (это еще одна функция) для фильтрации моих результатов. Это застало меня врасплох, когда я узнал, что функция Filter имеет тип (a -> Bool) -> [a] -> [a], что означает, что мой ввод для Filter должен быть логическим, а мой вывод для моего предиката должен быть логическим, чтобы его можно было кормить к Filter.

Это проблема, поскольку для фильтрации моих результатов из списка мне нужно ввести songName и songArtist (оба типа String) в предикат при рекурсивном просмотре результатов , и выведите songName и songArtist в Filter, чтобы он знал, какой именно кортеж нужно удалить из списка.

Я делаю это неправильно, или есть лучший способ go об этом?

Ответы [ 2 ]

6 голосов
/ 06 августа 2020

Я узнал, что функция фильтра имеет тип (a -> Bool) -> [a] -> [a]

filter :: (a -> Bool) -> [a] -> [a] принимает два параметра, предикат с подписью a -> Bool и списком элементов, и он возвращает список элементов, удовлетворяющих предикату. Таким образом, предикат является первым параметром.

, что означает, что мой ввод для Filter должен быть Boolean.

Нет, первый параметр имеет тип a -> Bool, поэтому это функция, которая сопоставляет элемент a с Bool, поэтому предикат .

Вы можете, например, создать функцию, которая проверяет, songName и songTitle совпадают с:

filterSales :: String -> String -> [(String, String, Int)] -> [(String, String, Int)]
filterSales artist title items = filter <b>p</b> items
    where <b>p</b> (artist', title', _) = artist == artist' && title == title'

Здесь p, таким образом, является предикатом, функцией, которая сопоставляет 3-кортеж с логическим значением. Предикат p вернет True для 3-кортежа, если первые два элемента равны artist и title соответственно.

5 голосов
/ 06 августа 2020

Это второй ответ, и существующий отличный, поэтому я покажу свой альтернативный вариант; в конце концов, два объяснения не могут быть хуже одного, верно?

То, что 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) является предикатом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...