2011-04-27 24 views
4

ハスケルを初めて使う人です。私はこのコードを書いた:コンテキスト(...)から推論できません(...)

deleteDuplicates :: [a] -> [a] 
deleteDuplicates [] = [] 
deleteDuplicates (x:xs) 
     | x == (head xs)  = x : (deleteDuplicates (tail xs)) 
     | otherwise    = x : (head xs) : (deleteDuplicates (tail xs)) 

このエラーは何を意味し、なぜそれが起こったのですか?何とか2つの異なるタイプを誤って比較していますか?

set2.hs:10:3: 
    Could not deduce (Eq a) from the context() 
     arising from a use of `==' at set2.hs:10:3-16 
    Possible fix: 
     add (Eq a) to the context of 
     the type signature for `deleteDuplicates' 
    In the expression: x == (head xs) 
     In a stmt of a pattern guard for 
       the definition of `deleteDuplicates': 
      x == (head xs) 
    In the definition of `deleteDuplicates': 
     deleteDuplicates (x : xs) 
          | x == (head xs) = x : (deleteDuplicates (tail xs)) 
          | otherwise = x : (head xs) : (deleteDuplicates (tail xs)) 

答えて

17

あなたのタイプの署名が間違っている:

deleteDuplicates :: [a] -> [a] 

あなたの関数は、任意の型のリスト、a上で動作することができますと言うが、それは真実ではないこと!あなたは後で電話します:

x == (head xs) 

したがって、あなたのタイプが等しいかどうかを比較できる必要があります。署名がなければなりません意味:それはあなたの明示的な型シグネチャを削除するには良いことだ。このような時

deleteDuplicates :: Eq a => [a] -> [a] 

は、GHCiの中で機能をロードし、インタプリタが(:t deleteDuplicates経由で)それは持つべきであると考えるものを入力し発見。

より多くのバグ

また、headのご使用は悪い考えがあります。 headは部分的な関数であり、xs == []の場合は失敗します。私はあなたがパターンマッチを拡大勧め:

deleteDuplicates (x1:x2:xs) 
    | x1 == x2 = ... 
    | otherwise = x1 : deleteDuplicates (x2:xs) 

otherwiseケースへの修正に気づきます。あなたはx2をスキップしましたが、x2がリストの次の要素と一致した場合はどうなりますか? [1,2,2,3]のようなものは1 /= 2を発見し、再帰はリストを得たでしょう[2,3] - おっと!

+0

'[1、2、2、3]'のようなものについては、すべての重複が削除されたリストを作成できません。私の悪い。 'Eq a =>'のことは私には新しかったので、 'a'型の要素は比較可能でなければならないのですか? – Pieter

+0

Pieter:基本的にはい。これは「typeclass制約」です。 '=='関数は 'Eq'型クラスで宣言されているので、式のインスタンスに対してのみ使用できます。 –

+0

@Pieter:平等に匹敵する、はい。 'Eq a =>'は 'a'は型クラス' Eq'のインスタンスでなければならないと言っています。型クラスは、インスタンスが実装するインタフェースを指定します。'Eq'クラスは二つの関数'(==) 'と'(/ =) 'を提供します。どちらも型' a - > a - > Bool'です。他の型クラスは他の関数を提供します。例えば、 'Ord'はより小さい、より大きい、より大きい、類似の順序付けテストを提供します。 –

1

発現

x == (head xs) 

aが型クラスEqのインスタンスでなければならないことを意味する、xsのメンバーに定義する==を必要とします。あなたの関数の型シグネチャは

deleteDuplicates :: Eq a => [a] -> [a] 
2

コンパイラに変更しaはinstanceofはEqある場合にのみ型シグネチャからそれがうまくできないことを語っています。

deleteDuplicates :: Eq a => [a] -> [a] 

あなたはa署名でそれに言及することによりEq型クラスのインスタンスである、コンパイラに指示する必要があります。

関連する問題