我正在尝试使用product
定义foldr
:
我可以用:
new_product xs = foldr (*) 1 xs
但不是:
new_product = foldr (*) 1
或:
new_product = \xs -> foldr (*) 1 xs
两个定义都产生相同的错误:
使用'folder'
时没有(可折叠的t0)的实例类型变量't0'是不明确的
相关绑定包括
new_product :: t0整数 - >整数
是某种类型错误吗?
我该如何解决?
答案 0 :(得分:3)
这是Monomorphism restriction正在发挥作用。解决方案是添加类型签名:
new_product :: (Foldable t, Num b) => t b -> b
new_product = foldr (*) 1
基本上,这里的问题是除非你在GHCi(禁用它)中,否则Haskell拒绝推断多态类型签名,除非你明确地为函数提供了变量。作为一个具体的例子:
f x = ... -- `f` can infer polymorphic type (in `x`)
f = \x -> ... -- `f` infers a monomorphic type
在您的情况下,f
为new_product
,x
为xs
。当您具有无点样式时,Haskell会尝试推断new_product
的单形签名并失败,因为它无法确定要选择哪个Foldable
实例(基于foldr
)。另一方面,当你包含xs
时,Haskell不再需要推断单态签名,因此一切正常。
这种疯狂是有道理的:关键是当你写f = ...
之类的东西时,很自然地认为f
只被评估过一次。然而,除非我们强迫f
变为单态,否则情况不一定如此。
使用与您的函数相关的示例:假设我推断p = num_product [1..1000]
具有类型Num a => a
(在这种情况下是最常见的类型),然后使用p :: Int
和{{1将导致我们评估p :: Integer
至少两次。