LINUX.ORG.RU

Haskell. Никак не могу сравнить 2 списка.

 , ,


0

2

Привет

учим в универех хаскель
есть лаба
суть задания - есть спискок названий и список товаров(Товар - новый тип с 3мя конструкторами). Надо для каждого названия извлечь из списка товаров товары с этим названием
получилось так

lookupTitle :: Title -> [Product] -> Maybe Product
lookupTitle _ [] = Nothing
lookupTitle title (x:xs)
	| (getTitle x) == title  = Just x
	| otherwise               = lookupTitle title xs

lookupTitles :: [Title] -> [Product] -> [Product]
lookupTitles _ [] = []
lookupTitles [] _  = []
lookupTitles (tx:txs) (px:pxs) = head(maybeToList (lookupTitle tx (px:pxs))) : (lookupTitles txs (px:pxs))

НО! Далее шла лаба с функциями высшего порядка
и теперь новое задание - переписать вот ту городулину на функциях высшего порядка. Желательно избежать явного прохода по спискам
родил такое, но незавершенное
lookupTitle :: Title -> [Product] -> Maybe Product
lookupTitle _ [] = Nothing
lookupTitle title xs = Just (head (filter (\x -> (getTitle x == title)) xs))

lookupTitles :: [Title] -> [Product] -> [Product]
lookupTitles _ [] = []
lookupTitles [] _  = []
lookupTitles (tx:txs) (pxl) = filter (\x -> not(null(lookupTitle tx pxl))) pxl
но, блин, оно не работает, и я никак не могу понять, как пройти по двум спискам
ну и с типами косяк из-за этого Maybe. Кстати вот тоже не знаю, как разMaybe'ить список

Maybe

O_o

Попробуй так:

lookupTitle :: Title -> [Product] -> Maybe Product
lookupTitle _ [] = Nothing
lookupTitle title xs = Try Please (head (filter (\x -> (getTitle x == title)) xs))

lookupTitles :: [Title] -> [Product] -> [Product]

lookupTitles [] _  = []
lookupTitles (tx:txs) (pxl) = reduce (\x -> not(null(lookupTitle tx pxl))) pxl
anonymous
()

Я не совсем понял зачем тебе Maybe, но я бы сделал вот так

type Title = String
data Product = 
	Product {
		   title :: String
		  ,price :: Int
		} 
		deriving (Eq, Show)
testProd :: [Product] 
testProd = [Product "banana" 24,  Product "apple" 52, Product "banana" 52]

lookupTitles :: Title -> [Product] -> [Product]
lookupTitles t p = filter (\x -> t == (title x)) p
Ok, modules loaded: Main.
*Main> testProd 
[Product {title = "banana", price = 24},Product {title = "apple", price = 52},Product {title = "banana", price = 52}]
*Main> lookupTitles "banana" testProd 
[Product {title = "banana", price = 24},Product {title = "banana", price = 52}]
*Main>

zinfandel ★★
()

какой-то ты глупый, делай лучше лабу на питоне

nokachi
()

\x -> (getTitle x == title)

Вместо анонимной функции можно использовать pointfree что короче: (==title) . getTitle

lookupTitle title xs = Just [...]

Как насчёт случая, в котором в списке товаров нет такого артикула? Иначе говоря нужна функция, которая возвращает Just x только тогда, когда она встретит искомый артикул. Есть такая отличная вещь как hoogle, который ищет функции по их сигнатуре:

*Main> :hgl a -> [a] -> Maybe a
Data.List find :: (a -> Bool) -> [a] -> Maybe a

Получаем

lookupTitle title = Data.List.find ((==title) . getTitle)  
Для второй функции действительно подойдёт filter:
lookupTitles ts = filter (flip elem ts . getTitle) 

HiddenComplexity
()
Ответ на: комментарий от Deleted

БелГУ :)
вряд ли бы ты хотел, если бы знал как преподают
хотя вот хаскель интересно

ii343hbka ★★★
() автор топика
Последнее исправление: ii343hbka (всего исправлений: 1)
Ответ на: комментарий от HiddenComplexity

ну вот весь косяк в том, что кроме filter,fold{l,r} и лямбд, по идее, нельзя ничем пользоваться
поэтому и велосипедю

да и лектор и препод на лабах разные
лабы принимает сложная мадама. Объясняй ей потом...

find крутая штука. Спасибо

ii343hbka ★★★
() автор топика
Последнее исправление: ii343hbka (всего исправлений: 3)

Простите моё недоумение, но зачем вообще в такой задаче связываться с монадами?

Как правильно написали, достаточно написать предикат, проверяющий для заданных Title и Product, что у продукта идентичное имя (или нет), и возвращающий true или false, и прогнать через filter исходный список с помощью этого предиката.

zinfandel правильно все расписал, только не стал предикат отдельно определять (ибо слишком примитивная проверка) и зафигачил как лямбду.

Дальше подключились товарищи, которые любят переусложнять, их лучше не слушать.

Virtuos86 ★★★★★
()
f :: Title -> [Product] -> [Product]
f title = filter ((==) title . getTitle)

fm :: [Title] -> [Product] -> [Product]
fm titles = filter (\x -> any (getTitle x ==) titles)
qnikst ★★★★★
()
Ответ на: комментарий от ii343hbka

задача халявная, какое у препода, сам думай.

qnikst ★★★★★
()
Ответ на: комментарий от s9gf4ult

Если Title Ord (а они Ord), то и Set быстрее будет, причем если их мало, то возможно быстрее HashMap, но задача не о том, а о том, как научиться комбинировать ФВП.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от qnikst

поскольку any не было в списке разрешенного, то:

any1 :: (a -> Bool) -> [a] -> Bool
any1 f = foldr (\n o -> f n || o)  -- или, что тоже самое foldr ((||) . f)

менее красивое, но более понятное:

any2 :: (a -> Bool) -> [a] -> Bool
any2 f = not . null . filter f 

-- или, что тоже самоме 
-- any2 = (((not . null) .) .) . filter

Ну и если филосовствовать, то все функции работы над списком это foldr :)

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)

lookupTitle должен давать не Maybe Product, а [Product]. Делается это простым применением функции filter.

Далее, имея такую загогулину, сделать [Product] из [Title] — задача для concatMap.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

понятное дело, что со списком продуктов было бы проще
но в задании сказано, что сигнатура именно String -> [Product] -> Maybe Product

ii343hbka ★★★
() автор топика
Ответ на: комментарий от ii343hbka

Глупо. Но одно в другое перегоняется легко.

Miguel ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.