【问题标题】:Haskell Type class using foldr使用 foldr 的 Haskell 类型类
【发布时间】:2015-12-03 15:01:56
【问题描述】:

我使用 foldr 编写了一个函数,用于确定列表或字符串的长度。我对为什么 Haskell 将类型类确定为 Num 有点困惑。当然字符串不包含在这个类中?然而,Haskell 坚持必须如此,否则该功能将无法正常工作。有人可以帮助澄清这是为什么吗?

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

【问题讨论】:

  • 您使用的是哪个版本? GHC 7.10 将您的函数类型推断为(Num b, Foldable t) => t a -> b
  • GHC 7.8.4 如果有帮助的话

标签: list haskell types typeclass


【解决方案1】:

我认为您的类型签名可能因您的声明而过于具体。这是我在 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 在 cmets 中提到的,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] 的。

万岁类型

【讨论】:

  • 非常感谢您如此清晰简洁地解释一切!
猜你喜欢
  • 2019-02-21
  • 1970-01-01
  • 2014-06-18
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 2016-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多