正如我在https://www.haskell.org/hoogle/?hoogle=Sum中看到的那样,这种差异是由于 - 我认为 - 存在两个不同的 sum 函数。也许这类似于 Java 中的多态性
确实,它是多态性,尽管不是以这种方式(请参阅此答案末尾的 PS)。注意...
sum :: (Num a) => [a] -> a
... 在被求和的数字的类型中已经是多态的,因此它可以与例如 的列表Integer
和 的列表一起使用Double
。这和...的区别
sum :: (Num a, Foldable t) => t a -> a
...是这在容器sum
的类型中也是多态的:
GHCi> -- +t makes GHCi print the types automatically.
GHCi> :set +t
GHCi> sum [1 :: Integer, 2, 3]
6
it :: Integer
GHCi> sum [1 :: Double, 2, 3]
6.0
it :: Double
GHCi> import qualified Data.Set as S
GHCi> :t S.fromList
S.fromList :: Ord a => [a] -> S.Set a
GHCi> sum (S.fromList [1 :: Double, 2, 3])
6.0
it :: Double
对于要与 一起使用的容器类型sum
,它必须具有类的实例,该Foldable
实例涵盖的功能,如sum
,可能表示为将容器扁平化为列表,然后以某种方式折叠它。
PS:您的书说的与您所看到的有所不同,因为直到最近,sum
Prelude 中的函数还具有不太通用的列表特定类型,并且您的书早于更改。调用两个不同的函数sum
,即使一个比另一个更通用,也会导致名称冲突(出于类似的原因,我导入了Data.Set
上面示例中限定的模块 - 这样做是个好主意因为它定义了一些函数,例如map
与 Prelude 函数发生冲突的函数,并且用它们来限定它们S.map
可以避免任何问题)。