2012-04-11 14 views
3

私はリスト内のアイテムのインスタンスをすべて削除しようとしています。これは、haskellを使用しています。私は本当に理解していないというエラーが出ます。誰かが私を助けて、私が正しいことをしているかどうかを教えてもらえますか?リストからすべてのインスタンスを削除する

deleteAllInstances :: (a, [l]) => a -> [l] -> [l] 
deleteAllInstances (a, []) = [] 
deleteAllInstances (i, (x:xs)) 
    | i == x = tail 
    | otherwise = x ++ tail 
    where tail = deleteAllInstances i xs 
+2

どのエラーが発生しますか? –

答えて

9

ファーストを使用することができ、型シグネチャは、不正な形式です。

deleteAllInstances :: (a, [l]) => a -> [l] -> [l] 

型シグネチャは、フォームConstraints(Ord a, Show a)ような型クラスを含む

name :: (Constraints) => type 

を有しています。この場合、関数は(==)を使用するため、Eq aという形式の制約が必要です。

関数定義は型部分と一致せず、引数としてペアをとるように定義しましたが、型シグネチャはそうではありません(定義は一掃されていない、型はカルトです)。

deleteAllInstances (a, []) = [] 
deleteAllInstances (i, (x:xs)) 
    | i == x = tail 
    | otherwise = x ++ tail 
    where tail = deleteAllInstances i xs 

は、あなたがリストの先頭に要素を接着する(++)を使用しますが、(++)は二つのリストを連結して、あなたはここで(:)を必要としています。

関数を定義する最も簡単な方法は、filter

deleteAllInstances :: Eq a => a -> [a] -> [a] 
deleteAllInstances a xs = filter (/= a) xs 

を使用することですが、あなたは、明示的な再帰を自分で行いたい場合は、

deleteAllInstances :: Eq a => a -> [a] -> [a] 
deleteAllInstances a (x:xs) 
    | a == x = rest 
    | otherwise = x : rest 
     where 
     rest = deleteAllInstances a xs 
deleteAllInstances _ _ = [] 
+0

数値だけでなく文字列でも動作させたい場合は – cclerville

+5

ここには何も記されていませんが、 'String'、' [String] 'を含む' Eq'のインスタンスであるすべての型で動作します。 。それは最も一般的な型を持つことができるので、おそらく動作する可能性があるすべてのものに対して機能します。 (あなたは '' aq'''''を '' aq'''を '' aq''とみなすことで '' Eq''制約を取り除くことができます; '' Eq''クラスはその関数を暗黙的なパラメータとして擬似的に提供します。) –

+1

あなたはそうです。ありがとう! :) – cclerville

3

私はあなたが=>(a, [l])をどうしようとしているのかわからないんだけど、私はそれは必要ないと思います。構文通常、aとlがどのような型を満たすべきかを指定するために予約されています。

また、関数定義で後で指定したように、関数には2つの引数、a[l]が必要です。しかし、関数の実装には1つの引数、つまりタプルだけが必要です。前に述べたように、タプルは引数の型を指定する役割しか果たしておらず、パターンマッチングもできません。あなたがfilterを使用して、それを書きたい場合は

deleteAllInstances :: a -> [l] -> [l] 
deleteAllInstances a [] = [] 
deleteAllInstances i (x:xs) 
    | i == x = rest 
    | otherwise = x : rest 
    where rest = deleteAllInstances i xs 

が、あなたは常に次のコード

deleteAllInstances :: a -> [a] -> [a] 
deleteAllInstances a = filter (/=a) 
3

私が実際にリストの内包が非常にあることを見つけますこのような問題の直感的な表記:

deleteAllInstances :: Eq a => a -> [a] -> [a] 
deleteAllInstances a list = [x | x <- list, x /= a] 
+0

これは高速ではありません - どちらも 'O(n)'です。また、 'filter'のような複数の関数を連鎖させることは、_Fusion_のために' O(n) 'になります。 'フィルタf。マップf '。フィルタf'''はまだ 'O(n)'です。 –

+0

複雑さは明らかに同じですが、GHCを理解する限り、コンパイルされたコードはリストの解説が単純な再帰に解決されるので、コンパイルされたコードが高速になり、フィルタリングの呼び出しを保存します。それは制約の複雑さに依存するかもしれません。 – thrau

+2

実際には、リスト内包表記はdo表記の代わりの構文に過ぎず、したがって、あなたの理解はまず 'list >> = \ a' - > 'a ='ならば 'else [] 'を返します。その後、オプティマイザは実際には単純な再帰への変換を行いますが、生成された関数への変換だけでなく、_Fusion_の対象となる他の関数に対しても行われます。 'filter'と' map'も融合の対象になります。そのため、生成されたコンパイラコードはあなたと同じでなければなりません。 __ghc-core__ユーティリティを試すことができます。オプティマイザが実際に行うことができることに驚くでしょう。 –

関連する問題