簡體   English   中英

Haskell - 無法將預期類型'b'與實際類型'a'匹配

[英]Haskell - Couldn't match expected type ‘b’ with actual type ‘a’

剛開始學習Haskell,我試圖實現一個max函數來遞歸地查找列表的最大值

max' :: (Num b) => [a] -> b
max' [] = 0
max' (x:xs)
    | x > max' xs = x
    | otherwise = max' xs

但在嘗試編譯時遇到錯誤

無法將預期類型'b'與實際類型'a'匹配'a''是由類型簽名綁定的剛性類型變量:max':: forall b a。 (Num b,Num a)=> [a] - > b at implementationFunctions.hs:5:1-34'b'是由類型簽名綁定的剛性類型變量:max':: forall b a。 (Num b,Num a)=> [a] - > b at implementationFunctions.hs:5:1-34

任何人都可以幫我理解什么是錯的?

max'作為輸入(基於所述簽名)的[a]一個列表a 但你回來了b 這意味着你已經寫了 - 無論列表中元素的類型如何 - 我們可以選擇任何類型b作為我們想要的輸出,只要它是Num b 但這沒有意義。 如果我們輸入字符串列表,我們當然可以計算“最大字符串”(按字典順序),但我們不能將其作為Num返回。

另一個問題是你使用(>) :: Ord a => a -> a -> Bool函數(作為一個守護者)。 但是,您沒有在函數簽名中指定輸入元素的類型必須是Ord類型類的實例。 所以你無法比較這些元素。

最小的修復是將輸入類型限制為b

max' :: (Ord b, Num b) => [b] -> b
max' [] = 0
max' (x:xs)
    | x > max' xs = x
    | otherwise = max' xs

話雖如此,如果我們提供一個空列表,返回0 沒有多大意義。 這將導致一個奇怪的事實,即max []實際上大於max [-1] :通常我們期望超集的最大值大於或等於集合的最大值。

因此, max'函數可能最好被視為非總函數:不是每個輸入都會導致輸出的函數。 在這種情況下,空列表不會。

我們可以將其重寫為錯誤:

max' :: Ord b => [b] -> b
max' [] = error "Empty list"
max' [x] = x
max' (x:xs@(_:_))
    | x > max' xs = x
    | otherwise = max' xs

所以現在有三種模式:(1)空列表,(2)單元列表,以及(3)具有至少兩個元素的列表。

然而,編寫錯誤並不總是處理非總函數的好方法,因為在類型簽名中看不到函數是非總函數。 另一個想做的就是使用Maybe b作為返回類型。 如果沒有最大值,這將是一個Nothing ,如果有一個,則為Just x

max' :: Ord b => [b] -> Maybe b
max' [] = Nothing
max' [x] = Just x
max' (x:xs@(_:_))
    | y <- max' xs = max x y
    | otherwise = Nothing

或更短:

max' :: Ord b => [b] -> Maybe b
max' [] = Nothing
max' [x] = Just x
max' (x:xs@(_:_)) = fmap (max x) (max' xs)

例如:

Prelude> max' []
Nothing
Prelude> max' [1,4,2,5]
Just 5
Prelude> max' [-3]
Just (-3)

你的函數會獲取一些東西並返回其中一個東西。 但是函數的類型簽名表明它需要一個東西[a]的列表並返回一個完全不同的東西b 這困擾了編譯器。 它無法將聲明的類型簽名與實際實現(又稱“類型檢查”)進行協調。

要解決此問題,請使類型簽名與實現匹配:

max' :: (Num a) => [a] -> a 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM