2013-07-10 35 views
0
versioncheck::String -> String -> Bool 
versioncheck [] [] = True 

versioncheck (x:xs) [] 
    |x /= 0 = False 
    |otherwise = versioncheck xs [] 

versioncheck (x:xs) (y:ys) 
    | x /= y = False 
    | otherwise = versioncheck xs ys 

爲什麼我得到錯誤 - 「定義versioncheck所需的Num Char實例」?這個錯誤的含義是什麼 - 「versioncheck定義所需的Num Char實例」?

+5

因爲您將'char'與行'| x/= 0 = False'中的數值進行比較。 –

+2

特別是'String'的意思是'[Char]',所以'x :: Char'。 – shachaf

回答

7

一種方法來解決這類問題和一個我可以推薦,是你的函數定義喂編譯器不附帶類型簽名,然後使用交互式環境檢查的類型,編譯器推斷爲功能。

在你的情況,如果我們定義

versioncheck []  []  = True 
versioncheck (x:xs) [] 
    |x /= 0     = False 
    |otherwise    = versioncheck xs [] 
versioncheck (x:xs) (y:ys) 
    | x /= y     = False 
    | otherwise    = versioncheck xs ys 

,然後在GHCI,查詢

> :type versioncheck 

它給我們

versioncheck :: (Eq a, Num a) => [a] -> [a] -> Bool 

做明確你的函數在兩個工作列表中包含相同類型的元素a,並且此類型爲a應該在類型爲Eq的類型中具有可以測試相等性的值以及類型爲Num的數值類型。

這些類別約束從何而來?第一個(對於Eq)是通過比較兩個輸入列表的元素與/=引入的。第二個(對於Num),您將第一個列表的元素與數值(0)進行比較。

現在,您提供的型號簽名爲String -> String -> Bool。由於字符串只是字符列表,因此會擴展爲[Char] -> [Char] -> Bool。將其與推斷的簽名進行比較,您的簽名將使用Char實例化類型變量a。至於Eq-關於a的約束而言,這是可以的,因爲Char確實是Eq的實例。然而,Char並非如需要,的Num的實例(和因此編譯器無法知道如何執行測試x /= 0);因此,類型錯誤。

一個解決方案是使用推斷的簽名,但如果它確實是您想要處理的字符列表,您將不得不擺脫測試x /= 0並將x與字符值進行比較。例如:

versioncheck :: String -> String -> Bool 
versioncheck []  []  = True 
versioncheck (x:xs) [] 
    |x /= '0'    = False 
    |otherwise    = versioncheck xs [] 
versioncheck (x:xs) (y:ys) 
    | x /= y     = False 
    | otherwise    = versioncheck xs ys 

(注意在'0'中的引號)編譯得很好。

+0

謝謝@dblhelix!很好的解釋! –

+0

我想這只是一個錯字,但你要比較的字符「0」,而不是「\ 0」字符 – dnaq

+1

danvari:我不知道該OP的函數的預期的語義概念。因此,我無法確定什麼是明智的檢查。無論如何:沒有錯字,只是猜測。 –

相關問題