求和函数中的不同类型
Different types in sum function
我是 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
的求和函数而不是另一种?你能给我解释一下这是怎么回事吗?
As I've seen in https://www.haskell.org/hoogle/?hoogle=Sum this difference is due to -I think- the existence of two different sum functions. Maybe it's something like polymorphism in 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
来限定它们可以避免任何问题)。
我是 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
的求和函数而不是另一种?你能给我解释一下这是怎么回事吗?
As I've seen in https://www.haskell.org/hoogle/?hoogle=Sum this difference is due to -I think- the existence of two different sum functions. Maybe it's something like polymorphism in 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
来限定它们可以避免任何问题)。