sum函数中的不同类型

时间:2016-11-15 18:18:43

标签: haskell types sum foldable

我是Haskell的新手,所以这可能是一个愚蠢的问题。我正在读一本书,其中:type sum应该显示sum :: (Num a) => [a] -> a。而不是消息是sum :: (Num a, Foldable t) => t a -> a。正如我在https://www.haskell.org/hoogle/?hoogle=Sum中看到的那样,这种差异是由于 - 我认为 - 存在两个不同的和函数。也许它就像Java中的多态,我刚刚开始,我不知道Haskell是如何工作的。

所以我的问题是:我如何使用类型为sum :: (Num a) => [a] -> a的sum函数而不是另一个?你能解释一下这里发生了什么吗?

1 个答案:

答案 0 :(得分:2)

  

正如我在https://www.haskell.org/hoogle/?hoogle=Sum中所见,这种差异是由于 - 我认为 - 存在两种不同的和函数。也许它就像Java中的多态性

确实是多态性,但不是这样(参见本答案末尾的P.S.)。请注意......

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一起使用的容器类型,它必须具有the Foldable class的实例,其中包含的函数(如sum)可能表示为将容器展平为列表然后以某种方式折叠它。

P.S。:你的书说的不同于你所看到的东西,因为直到最近,Prelude中的sum函数过去常常使用不那么通用的特定于列表的类型,而你的书早于改变。有两个不同的函数sum,即使一个严格比另一个更通用,也会导致名称冲突(这是因为我导入了上面示例中限定的Data.Set模块的类似原因 - 这样做是个好主意,因为它定义了一些与Prelude函数冲突的map函数,并使用S.map来限定它们,避免任何问题)。