2016-05-05 2 views
2

Я хочу написать полиморфную функцию, которая вводит два списка и сообщает мне, содержат ли эти два списка общий элемент. Моя попытка написания этой функции выглядит следующим образом:Функция наложения перекрытий

overlaps :: (Eq a) => [a] -> [a] -> Bool 
overlaps x:xs y:ys 
    | x `is_element_of` ys = True 
    | otherwise = False 

где

is_element_of :: (Eq a) => a -> [a] -> Bool 
is_element_of e list = case list of 
[] -> False 
x: xs -> e == x || e `is_element_of` xs 

Однако это не работает ... Можно ли шаблон матч против двух списков? Является ли это возможным способом написания этой функции?

+0

Соответствие шаблону не работает, потому что все шаблоны в аргументах функций должны быть в круглых скобках. Кроме того, если вы сопоставляете шаблон во втором списке, как это, вы выбрасываете свой первый элемент, который вам, вероятно, не нужен. – jPlatte

+3

'' 'overlaps xs = any (' elem' xs) '' ' –

+1

упорядочены ли списки? Потому что тогда вы можете повысить производительность. –

ответ

0

Я думаю, что вы хотите что-то вроде этого (непроверенные):

overlaps :: (Eq a) => [a] -> [a] -> Bool 
overlaps [] _  = False 
overlaps _ []  = False 
overlaps (x:xs) list = x `myelem` list || overlaps xs list 

myelem :: (Eq a) => a -> [a] -> Bool 
myelem _ []  = False 
myelem x (y:ys) = x == y || myelem x ys 

AFAIK, используя шаблон, соответствующий appropach более идиоматических.

2

Ваша функция is_elem_of уже существует в пакете Data.List как elem. Используя это, overlaps легко писать.

overlaps []  _ = False 
overlaps (x:xs) ys = x `elem` ys || overlaps xs ys 

Как вы можете сказать, можно сопоставить образец по спискам. Если вы хотите написать функцию без сопоставление образцов по спискам, вы можете использовать функцию foldr.

overlaps xs ys = foldr (\x acc -> x `elem` ys || acc) False xs 
+1

Над 'foldl' не хватает аргумента. Кроме того, я бы предпочел бы 'foldr' здесь, так как' foldl' всегда просматривает все 'xs', и нет необходимости делать это. – chi

+0

@chi, спасибо, что указал ошибка. Я понял, что 'foldr' был строгим в обоих аргументах своей функции, а' foldl' ленился. Это неправильно? Если нет, значит, это не означает, что * 'foldr' * будет сканировать весь список, а *' foldl' * будет замыкаться на короткое замыкание, как только '||' ударит значение 'True'? – Kwarrtz

+0

@Kwarrtz, 'foldr' является более ленивым, чем' foldl'. Фактически вы можете реализовать 'foldl' с помощью' foldr' (GHC делает это!), Но не наоборот. – dfeuer

Смежные вопросы