【问题标题】:Scala structural type as function type paramScala 结构类型作为函数类型参数
【发布时间】:2014-06-01 08:41:15
【问题描述】:

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

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

有没有办法解决这个问题?

【问题讨论】:

  • 我相信 Int 和 String 都没有 + 方法。在这种情况下,隐式转换可能会有所帮助。

标签: scala duck-typing structural-typing


【解决方案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")

【讨论】:

    【解决方案2】:

    我认为 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)
    

    不幸的是,在很多这样的情况下,您希望推断出类型,但事实并非如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 2013-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      相关资源
      最近更新 更多