Не удалось вывести (уравнение) из контекста (...) - PullRequest
4 голосов
/ 27 апреля 2011

Я новичок в Хаскеле.Я написал этот код:

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

Что означает эта ошибка и почему она произошла?Я случайно как-то сравниваю два разных типа?

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))

Ответы [ 3 ]

18 голосов
/ 27 апреля 2011

Ваша подпись неверна:

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] - упс!

2 голосов
/ 27 апреля 2011

Компилятор говорит вам, что из одной только сигнатуры типа он не может работать, если a является экземпляром Eq.

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

Вы должны сообщить компилятору, что aявляется экземпляром класса Eq , упомянув его в подписи.

1 голос
/ 27 апреля 2011

Выражение

x == (head xs)

требует, чтобы == было определено для членов xs, что означает, что a должен быть экземпляром класса типов Eq. Измените тип подписи вашей функции на

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