Haskell:用foldr定义产品 [英] Haskell: Define product with foldr
问题描述
我试图用 foldr
定义 product
:
我可以这样做:
new_product xs = foldr(*)1 xs
但不是:
new_product = foldr(*)1
或:
new_product = \xs - >这两个定义都会产生相同的错误:
$ b
没有使用'folder'引起的(可折叠t0)实例
类型变量't0'不明确
相关绑定包括:
new_product :: t0整数 - >整数
是某种类型的错误吗?
我该如何解决它?
这是工作时的。解决方法是添加一个类型签名:
new_product ::(可折叠t,数字b)=> t b - > b
new_product = foldr(*)1
<从本质上讲,这里的问题是,除非你在GHCi中(这是禁用的),否则Haskell拒绝推断一个多态类型签名,除非你显式地为函数指定了变量。作为一个具体的例子:
fx = ... - `f`可以推断多态类型(在`x`)
f = \ x - > ... - `f`推断出单形态
在你的情况下, f
是 new_product
和 x
是 xs
。当你拥有无点式的风格时,Haskell试图推断出 new_product
的单形签名,并且因为无法确定哪个可折叠 code>实例来选择(基于
foldr
)。另一方面,当包含 xs
时,Haskell不再需要推断单形签名,因此一切正常。
这种疯狂是有原因的:关键是当你写 f = ...
之类的东西时,很自然地假设 f
只会被评估一次。然而,除非我们强制 f
是单形的,否则不一定是这种情况。
与你的函数相关:假设我推断 p = num_product [1..1000]
的类型为 Num a =>一个
(这种情况下最常用的类型),然后使用 p :: Int
和 p :: Integer
将使我们至少评估两次
p
。
因此Haskell决定不要 generalize 顶层绑定:你只能推导出具有明确变量的函数的多态签名(即在等号的左侧)。也就是说,如果你想明确地写出一个多态的类型签名,你可以自由地这样做。
I'm trying to define product
with foldr
:
I could do it with:
new_product xs = foldr (*) 1 xs
but not:
new_product = foldr (*) 1
or:
new_product = \xs -> foldr (*) 1 xs
Both definition produce the same error:
No instance for (Foldable t0) arising from a use of ‘folder’
The type variable ‘t0’ is ambiguous
Relevant bindings include
new_product :: t0 Integer -> Integer
Is it some kind of type error?
How could I fix it?
This is the Monomorphism restriction at work. The solution is to add a type signature:
new_product :: (Foldable t, Num b) => t b -> b
new_product = foldr (*) 1
Essentially, the problem here is that unless you are in GHCi (where this is disabled) Haskell refuses to infer a polymorphic type signature unless you explicitly have variables for the function. As a concrete example:
f x = ... -- `f` can infer polymorphic type (in `x`)
f = \x -> ... -- `f` infers a monomorphic type
In your case, f
is new_product
and x
is xs
. When you have the point-free style, Haskell attempts to infer a monomorphic signature for new_product
and fails because it can't figure out which Foldable
instance to choose (based on foldr
). On the other hand, when you include the xs
, Haskell is no longer bound to infer a monomorphic signature, hence everything works.
There is reason to this madness: the point is that when you write something like f = ...
it is natural to assume that f
only gets evaluated once. Yet, unless we force f
to be monomorphic, that isn't necessarily the case.
To use an example related to your function: suppose that I infer that p = num_product [1..1000]
has type Num a => a
(the most general type in this case), then using p :: Int
and p :: Integer
will cause us to evaluate p
at least twice.
Haskell has therefore decided not to generalize top-level bindings: you only infer polymorphic signatures for functions that have their variables explicit (ie. on the left hand side of the equal). That said, if you wish to explicitly write a polymorphic type signature, you are free to do so.
这篇关于Haskell:用foldr定义产品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!