使用foldr的Haskell Type类

时间:2015-12-03 15:01:57

标签: list haskell types typeclass

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

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

1 个答案:

答案 0 :(得分:3)

我认为您的类型签名可能因您的声明而过于具体。这就是我在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成为myLength :: (Foldable t, Num b) => t a -> b用于许多不同的数据结构而不是单独的列表。在GHC 7.10上,您的函数确实会有(Foldable t) => t a的类型推断。请注意[a]如何概括lsof | grep ":$port " | awk '{print $2}'

HOORAY TYPES