我使用foldr编写了一个函数来确定列表或字符串的长度。我为什么Haskell确定类型类是Num有点困惑。当然字符串不包含在这个类中?然而,Haskell坚持认为必须如此,否则该功能不会起作用。有人可以帮助澄清这是为什么吗?
myLength' :: (Num a) => [a] -> Int
myLength' xs = foldr (\x acc -> 1 + acc) 0 xs
答案 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