2016-05-05 7 views
2

2つのリストを入力し、これらの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

関数の引数でパターンマッチがすべて括弧内になければならないため、パターンマッチは機能しません。また、このように2番目のリストでパターンマッチングを行うと、おそらく望ましくない最初の要素を捨ててしまいます。 – jPlatte

+3

'' 'は重複していますxs = any(' elem' xs) '' ' –

+1

リストはオーダーされていますか?そのため、パフォーマンスを向上させることができます。 –

答えて

0

私はあなたが(未テスト)このような何かをしたいと思います:パターンマッチングappropachを使用して

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 

私の知る限りでは、より慣用的です。

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'の上には引数がありません。さらに、 'foldl'は常に' foldl'が 'xs'全体をスキャンし、それを行う必要がないので、ここでは' foldr'を好むでしょう。 – chi

+0

@chi、エラーを指摘していただきありがとうございます。 'foldr'は関数の両方の引数で厳密であり、' foldl'は怠け者でした。それは間違っていますか?そうでなければ、 'foldr' *はリスト全体を走査するのに対し、' foldl' *は '||'が 'True'の値に達するとすぐに短絡するでしょうか? – Kwarrtz

+0

@Kwarrtz、 'foldr'は' foldl'よりもレイジーです。実際、 'foldl'を使って' foldl'を実装することができます(GHCはこれを行います!)。 – dfeuer

関連する問題