2013-04-22 62 views
12
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's可以與'=='比較,你必須把這個信息放在類型簽名中。 – 2013-04-22 19:00:50

+0

因爲'(==)'是'Eq'類的成員。所以你只能在'Eq'實例的類型中使用它。 – 2013-04-22 19:01:13

+1

真實世界haskell chap 3?我也是! – Jason 2014-01-31 03:58:30

回答

27

您正在比較使用==的兩種a類型的項目。這意味着a不能只是任何類型 - 它必須是Eq的實例,因爲==的類型是(==) :: Eq a => a -> a -> Bool

您可以通過a添加Eq約束你的函數的類型簽名解決這個問題:

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

順便說一句,還有一個更簡單的實現使用reverse此功能的方法。

+8

根據lambdabot,'isPalindrome = reverse >> =(==)':D – fredoverflow 2013-04-22 20:41:26

+1

@FredOverflow哇,這是瘋狂的晦澀難懂。 :) – augustss 2013-04-23 09:19:40

+1

它爲函數使用monad實例,就像'join(+)2 = 4'一樣。但是'isPalindrome xs = xs == reverse xs'是完全合理的。 – 2013-11-29 05:13:24

0

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 

添加均衡例如用於

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

這個實例化說,現在,一個其類型可以與和(e可比== x)不會失敗。