这些错误是最好的一种,因为它们可以确定你犯的类型错误。
那么让我们来做一些手动类型推断。让我们考虑表达式:
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