這些錯誤是最好的一種,因爲它們可以確定你犯的類型錯誤。
那麼讓我們來做一些手動類型推斷。讓我們考慮表達式:
map (\y -> (if (getAvg x > y) then 1 else 0)) x
有一些限制,我們知道蝙蝠:
map :: (a -> b) -> [a] -> [b] -- from definition
(>) :: Num a => a -> a -> Bool -- from definition
getAvg :: [Integer] -> Double -- from type declaration
1, 0 :: Num a => a -- that's how Haskell works
x :: [Integer] -- from type declaration of smallerThanAVG
現在,讓我們看看大表達式。
expr1 = getAvg x
expr2 = (expr1 > y)
expr3 = (if expr2 then 1 else 0)
expr4 = (\y -> expr3)
expr5 = map expr4 x
現在讓我們反向工作。expr5
與smallerThanAVG
的RHS相同,所以這意味着它與您聲明的結果類型相同。
expr5 :: Integer -- wrong
然而,這不符合我們的其他約束:中map
結果必然是[b]
一些b
。 Integer
絕對是而不是的一個列表(儘管如果你變得諷刺,它可能被強制到一個位列表中)。你可能意思是sum
這個名單。
expr6 = sum expr5
sum :: Num a => [a] -> a
現在讓我們繼續前進吧。
expr1 :: Double -- result type of getAvg
y :: Double -- (>) in expr2 requires both inputs to have the same type
expr4 :: (Integer -> [a]) -- because for `map foo xs` (expr5)
-- where xs :: [a], foo must accept input a
y :: Integer -- y must have the input type of expr4
這裏存在衝突:y
不能既是一個Double
和Integer
。我可以等價地重申:x
不能同時是編譯器說的[Double]
和[Integer]
。所以tl; dr,踢球者是(>)
不比較不同類型的Num
s。這類問題的模因是:「需要更多fromIntegral
」。
(getAvg x > fromIntegral y)
可能是我見過的約哈斯克爾,感謝最全面的信息。 – Asaf