Haskell:用foldr定义产品 [英] Haskell: Define product with foldr

查看:213
本文介绍了Haskell:用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆