如何在Scala中设置绑定的类型参数以使数字具有泛型功能? [英] How to set type parameter bound in scala to make generic function for numerics?

查看:48
本文介绍了如何在Scala中设置绑定的类型参数以使数字具有泛型功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个适用于所有数值类型的求和函数.

I want to make a sum function that works with all Numeric types.

这有效:

object session {
  def mapReduce[A](f: A => A, combine: (A, A) => A, zero: A, inc: A)
                  (a: A,b: A)
                  (implicit num:Numeric[A]): A = {
    def loop(acc: A, a: A) =
    if (num.gt(a, b)) acc
    else combine(f(a), mapReduce(f, combine, zero, inc)(num.plus(a, inc), b))
    loop(zero, a)
  }

  def sum(f: Int => Int)
         (a: Int, b: Int) : Int = {
    mapReduce(f, (x: Int, y: Int) => x + y, 0, 1)(a, b)}
  sum(x => x)(3, 4)  //> res0: Int = 7

  def product(f: Int => Int)
             (a: Int, b: Int): Int = {
    mapReduce(f, (x: Int, y: Int) => x * y, 1, 1)(a, b)}
  product(x => x)(3, 4) //> res1: Int = 12

  def fact(n: Int) = product(x => x)(1, n)
  fact(5) //> res3: Int = 120
}

但是当我尝试使总和像这样时:

but when I try to make sum generic like this:

def sum[A](f: A => A)
           (a: A, b: A)
           (implicit num:Numeric[A]): A = {
  mapReduce(f, (x: A, y: A) => num.plus(x, y), 0, 1)(a, b)}
sum(x => x)(3.0, 4.0) // should be 12.0

我在f上收到此错误

类型不匹配;找到:A =>必需:任何=>任何

type mismatch; found : A => A required: Any => Any

当我将其传递给mapReduce时.那么我该怎么做才能使sum接受任何数值?

when i pass it to mapReduce. So what do i need to do to make sum accept any Numeric value?

推荐答案

如果我没记错的话,其他答案几乎是正确的,除了在调用 mapReduce时必须使类型显式代码>,而不是在调用 sum 时.

If I'm not mistaken, the other answer is almost correct except for the fact that the type has to be made explicit when calling mapReduce instead of when calling sum.

因此,在 sum 的通用定义中,您可能想要执行以下操作:

So in your generic definition of sum, you might want to do this:

def sum[A](f: A => A)(a: A, b: A)(implicit num: Numeric[A]): A =
  mapReduce[A](f, num.plus, num.zero, num.one)(a, b)

但是对于打字员来说,这不足以推断出 A 的具体类型,例如调用 sum(x => x)(3.0,4.0)时的 Double .原因是键入器从左到右从第一个到最后一个参数列表.您的第一个参数列表声明 f:A =>A ,只有第二个参数列表定义了(a:A,b:A).一旦键入器到达第一个参数列表的末尾,它就不知道确切的 A 是什么,因此将 A 的类型固定为某些抽象" <代码> A .此时,它唯一了解 A 的地方是它是 Any 的子类型.然后,当键入器进入第二个参数列表时,理论上它可以将 A 推断为 Double 或您的具体类型是什么,但是正如在确定类型之前所说的那样.这只是Scala打字机的一个缺陷,一旦您掌握了它,就可以轻松地绕开它.更准确地说,您要做的就是通过像这样切换第一和第二参数列表来帮助打字员:

That's however not enough for the typer to infer the concrete type of A, e.g. Double when calling sum(x => x)(3.0, 4.0). The reason for this is that the typer is going from first to last parameter list, left to right. Your first parameter list declares f: A => A and only the second parameter list defines (a: A, b: A). Once the typer reaches the end of the first parameter list, it doesn't know what A exactly is, and hence it fixes the type of A to some "abstract" A. The only thing that it knows about A at this point is that it is a subtype of Any. When the typer then gets to the second parameter list, it could theoretically infer A as Double or whatever your concrete type is, but as said before the type has already been fixed. This is just a flaw of Scala's typer which can easily be circumvented once you get the hang of it. More precisely, all you have to do is help the typer by switching the first and second parameter lists like so:

def sum[A](a: A, b: A)(f: A => A)(implicit num: Numeric[A]): A =
  mapReduce[A](f, num.plus, num.zero, num.one)(a, b)

然后可以调用 sum ,而无需明确说明类型,例如

Then it's possible to call sum without being explicit about the type, e.g.

Console println sum(3.0, 4.0)(x => x)     // 7.0

这篇关于如何在Scala中设置绑定的类型参数以使数字具有泛型功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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