[英]Haskell - “Type error in application”: “unification would give infinite type”
我正在開始使用Haskell,但是我試圖制作的這種平等檢查並沒有成功。
我有一個函數countLetter a [b] c
,其中a
是char, b
是chars列表, c
是int。 (類型聲明通過罰款。)但是我遇到了這個表達式的問題:
if a == head(b)
給我以下消息:
Type error in application
*** Expression : a == head b
*** Term : a
*** Type : [a]
*** Does not match : a
*** Because : unification would give infinite type
如果需要,我的代碼是完整的:
countLetter :: char -> [char] -> int
countLetter a [b] c = if null b
then []
else
if a == head(b)
then countLetter a tail(b) c+1
else
countLetter head(b) tail(b) c
任何幫助或建議將不勝感激。 謝謝。
首先,Haskell中的類型以大寫字母開頭。 如果在類型簽名中使用以小寫字母開頭的標識符,則將它們解釋為類型變量。 所以你的類型char -> [char] -> int
與a -> [a] -> b
,這對你的函數來說不是一個合理的類型。 你想要的Char -> [Char] -> Int
。
其次, []
不是Int
類型的有效值。 修復您的類型簽名應該會產生一條錯誤消息,告訴您不那么模糊的術語。
然后,它也應該告訴你, null b
是一種錯誤,因為b
是類型的Char
(你的函數的第二個參數是類型[Char]
與你匹配它與模式[b]
結合b
的單包含在該列表中的Char
)和null
將列表而不是Char作為其參數。
最后一點澄清:
函數的第二個參數是一個列表。 通過在參數列表中編寫[b]
,可以將該參數與模式[b]
匹配。 換句話說,寫countLetter a [b] c = blabla
與寫入相同:
countLetter a theList c =
case theList of
[b] -> blabla
所以你要說:“函數的第二個參數必須是一個包含一個元素的列表,該元素應該被稱為b
”。 這不是你想要說的。 你想要說的是“函數的第二個參數(順便提一下,它是一個列表)應該被稱為b
”。 為此,你只需寫入countLetter abc = blabla
。
類型列表的參數不必以與其他類型的參數不同的方式表示。
您將遇到的另一個錯誤是:
countLetter head(b) tail(b) c
按照規則,這是相同的
countLetter head b tail b c
即你只用3個參數調用你的countLetter函數,當它只需要3個(根據第一個等式)或2個(根據你的類型簽名)。 (這是編譯器非常不滿意的另一點。)
你可能想要這個:
countLetter (head b) (tail b) c
同樣:
countLetter a tail(b) c+1
是相同的
(countLetter a tail b c) + 1
但你可能想要:
countLetter a (tail b) (c+1)
除了提供修復函數的其他答案之外,您可能還需要考慮以更具成分的方式編寫它。 具體來說,通過構建其他標准函數來尋找編寫函數的方法。 假設您有一個函數將刪除與列表中的測試字母不相等的所有內容。
myFilter :: Char -> [Char] -> [Char
myFilter = ...
使用myFilter
,您將只剩下一個列表,其中只包含您要檢查的元素。 此時,您可以使用length
來獲取列表的長度:
countLetter :: Char -> [Char] -> Int
countLetter a b = length $ myFilter a b
所以現在你只需要定義myFilter
,這可以使用標准的Prelude函數filter
來完成
myFilter a b = filter (==a) b
對於一個小的函數,創建我們自己的定義幾乎不值得,因為你可以寫
countLetter a b = length $ filter (== a) b
現在,在ghci中定義它以查看它為函數countLetter
找到的類型
Prelude> let countLetter a b = length $ filter (== a) b
Prelude> :t countLetter
countLetter :: Eq a => a -> [a] -> Int
看見沒有Char
! 實現不依賴於元素是字母,只是可以比較它們的相等性(這也適用於您的方法)。 所以ghci在計算的類型中反映出來。 但你可以通過用Char
代替a
來看到這正是你想要的類型。
許多功能程序員傾向於找到這種方法,即通過組合較小的部件來構建功能,特別容易推理,因此它很常見。 特別是在使用列表時,您可能希望查看是否可以使用所謂的高階函數(例如map
, filter
或fold)編寫實現,而不是使用遞歸。 有時遞歸是最清晰的方式,但我希望你經常會發現函數組合是一種更好的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.