Haskell 使用 foldr 输入 class

Haskell Type class using foldr

我使用 foldr 编写了一个函数来确定列表或字符串的长度。我有点困惑为什么 Haskell 确定类型 class 是 Num。 class 中肯定不包含字符串吗?然而 Haskell 坚持必须如此,否则该功能将无法工作。谁能帮忙解释一下这是为什么?

myLength' :: (Num a) => [a] -> Int
myLength' xs = foldr (\x acc -> 1 + acc) 0 xs

我认为您的类型签名可能因您的声明而变得过于具体。这是我在 GHCi 中得到的:

> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b

> :t foldr (\x acc -> acc + 1)
... :: Num b => b -> [a] -> b

+Num 约束的来源。它仅适用于 b 类型,因为 acc 的类型与 b 统一。没有进一步的限制出现,因为我们没有对 x :: a.

做任何事情
> :t foldr (\x acc -> acc + 1) 0
... :: Num b => [a] -> b

0 很容易与 Num b => b 统一,除了我们放下一个箭头之外没有任何变化。

> :t \xs -> foldr (\x acc -> acc + 1) 0 xs
... :: Num b => [a] -> b

我们引入了一个没有特定类型的参数 xs,它很容易与 [a] 统一。没有什么改变。所以我们的最终类型应该是

myLength :: (Num b) => [a] -> b
myLength = foldr (\_ acc -> 1 + acc) 0

对字符串有效。 myLength "hello" => 5 等等。

正如 Lee 在评论中提到的,foldr 的类型在 GHC 7.10 中更改为 Foldable t => (a -> b -> b) -> b -> t a -> b 作为 Foldable Traversable in Prelude Proposal 的一部分,这允许使用 foldr在许多不同的数据结构上,而不仅仅是列表。在 GHC 7.10 上,您的函数确实具有 myLength :: (Foldable t, Num b) => t a -> b 的类型推断。请注意 (Foldable t) => t a 如何概括 [a].

万岁类型