【问题标题】:Different types in sum functionsum 函数中的不同类型
【发布时间】:2016-11-15 18:18:42
【问题描述】:

我是 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 函数而不是另一个?你能解释一下这里发生了什么吗?

【问题讨论】:

  • 列表sumPrelude中,即默认在范围内,所以如果你不做任何特别的事情,你会使用它。要引用另一个sum,您需要导入Data.Foldable。那么你到底有什么疑问呢?如果有歧义,编译器应该报告它。
  • @laughedelic 在最近的 GHC 版本中,Prelude sumData.Foldable 中的相同。
  • 自 GHC 7.10 以来,Prelude 中的几个函数具有通用签名。不再有 sum :: Num a => [a] -> a - 新的 sum :: (Num a, Foldable t) => t a -> a 仍然适用于列表(就像旧的一样),但它现在也适用于其他东西(SequencesSets
  • @duplode 酷!我不知道这些变化。
  • 新 Prelude 类型的通用性很容易混淆。每当您在约束中看到 Foldable t 时,将每个 t a 替换为 [a] 以获得更简单的情况。

标签: haskell types sum foldable


【解决方案1】:

正如我在https://www.haskell.org/hoogle/?hoogle=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 一起使用的容器类型,它必须具有the Foldable class 的实例,它涵盖的功能,如sum,可能表示为将容器扁平化为列表然后折叠它以某种方式。

P.S.:您的书所说的与您所看到的有所不同,因为直到最近,Prelude 中的 sum 函数曾经具有不太通用、特定于列表的类型,而您的书早于更改。有两个不同的函数称为sum,即使一个比另一个更通用,也会导致名称冲突(出于类似的原因,我导入了上面示例中限定的Data.Set 模块——它是这样做是个好主意,因为它定义了一些与 Prelude 函数发生冲突的函数,例如 map,并且使用 S.map 来限定它们可以避免任何问题)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 2021-02-18
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多