Scala结构类型作为函数类型参数

时间:2014-06-01 08:41:16

标签: scala duck-typing structural-typing

我想创建一些"通用加法器"功能,适用于所有支持" +"操作。 我尝试过将结构类型作为函数类型param,但这不能编译:

def f[T <: { def +(x: T): T} ](a: T, b: T): T = a + b

error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement

有没有解决这个问题的方法?

2 个答案:

答案 0 :(得分:1)

除了使用类型类之外,我不认为这个问题有解决方法。但是,您需要对要处理的类型进行隐式转换。

Scala语言规范说

  

在结构细化中的方法声明中,类型为   任何值参数都只能引用类型参数或抽象   细化内包含的类型。也就是说,它必须参考   要么是方法本身的类型参数,要么是类型   精炼中的定义。此限制不适用于   函数的结果类型。

这就是您收到错误的原因。

示例实现可能如下所示

trait AddLike[T] {
  def +(x: T): T
}

def f[T <% AddLike[T]](a: T, b: T): T = a + b

implicit def num2AddLike[T](a: T)(implicit ev: Numeric[T]) = new AddLike[T] { def +(b: T) = ev.plus(a, b) }
implicit def str2AddLike(a: String) = new AddLike[String] { def +(b: String) = a + b }

f(1, 2)
f("one", "two")

答案 1 :(得分:0)

我认为Scala中没有办法创建一个可以自动处理可添加的所有类型的通用函数实例。但是,在Scala源代码中,该函数可以写成_ + _,在某些情况下,将推断出类型。

def triple[T](value: T)(add: (T, T) => T): T = add(add(value, value), value)

triple(10)(_ + _)
triple("w")(_ + _)

def tripler[T](add: (T, T) => T): T => T = (value: T) => triple(value)(add)

val tripleDouble: Double => Double = tripler(_ + _)
tripleDouble(3.2)

不幸的是,在许多这样的情况下,您希望推断出类型,而且它们不会被推断。