一種方法來解決這類問題和一個我可以推薦,是你的函數定義喂編譯器不附帶類型簽名,然後使用交互式環境檢查的類型,編譯器推斷爲功能。
在你的情況,如果我們定義
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'
中的引號)編譯得很好。
因爲您將'char'與行'| x/= 0 = False'中的數值進行比較。 –
特別是'String'的意思是'[Char]',所以'x :: Char'。 – shachaf