Haskell: Нет экземпляра для (Eq a), возникающего из-за использования `== '

isPalindrome :: [a] -> Bool
isPalindrome xs = case xs of 
                        [] -> True 
                        [x] -> True
                        a -> (last a) == (head a) && (isPalindrome (drop 1 (take (length a - 1) a)))

main = do
    print (show (isPalindrome "blaho"))

приводит к

No instance for (Eq a)
  arising from a use of `=='
In the first argument of `(&&)', namely `(last a) == (head a)'
In the expression:
  (last a) == (head a)
  && (isPalindrome (drop 1 (take (length a - 1) a)))
In a case alternative:
    a -> (last a) == (head a)
         && (isPalindrome (drop 1 (take (length a - 1) a)))

Зачем возникает эта ошибка?

Ответ 1

Вы сравниваете два элемента типа a с помощью ==. Это означает, что a не может быть просто типом - он должен быть экземпляром Eq, так как тип == равен (==) :: Eq a => a -> a -> Bool.

Вы можете исправить это, добавив ограничение Eq на a к типу вашей функции:

isPalindrome :: Eq a => [a] -> Bool

Кстати, существует гораздо более простой способ реализовать эту функцию с помощью reverse.

Ответ 2

Описание hammar правильное.

Еще один простой пример:

nosPrimeiros :: a -> [(a,b)] -> Bool
nosPrimeiros e [] = False
nosPrimeiros e ((x,y):rl) = if (e==x)   then True
                                        else nosPrimeiros e rl

Ошибка (e == x) не будет выполнена для этой сигнатуры функции. Вам нужно заменить:

nosPrimeiros :: a -> [(a,b)] -> Bool

добавление экземпляра Eq для

nosPrimeiros :: Eq => a -> [(a,b)] -> Bool

В этом экземпляре указано, что теперь a имеет тип, который может быть сопоставим с и (e == x) не будет терпеть неудачу.