在函数中需要Scala隐式类

mwl*_*lon 2 scala implicit

我的目标是为各种类型(时间戳,日期等)配备他们默认可能没有的好的属性(订购, - 等).我正在做这样的事情:

trait NiceProperties[T] {
  def -(t: T): Double
  def +(d: Double): T
  ...
}

implicit class BetterTimestamp(val t: Timestamp) extends NiceProperties[Timestamp] {
  override def -(Timestamp): ...
}
Run Code Online (Sandbox Code Playgroud)

这一切都正常,直到我需要将它传递给一个假定的函数NiceProperties:

def myUtil[T](t: NiceProperties[T]): T = {
  (t + 1.0) + 1.0
}
Run Code Online (Sandbox Code Playgroud)

这现在失败了,因为函数缺少隐式证据表明类T可以隐式向上转换NiceProperties[T],所以它不能添加(t + 1.0): T到double.

有没有办法将隐式类的证据传递给函数?或者,有更好的模式吗?

Aki*_*Aki 5

你可以通过把你NiceProperties[T]变成一个知道如何添加,总和......类的两个值来解决你的问题T:

trait NiceProperties[T] {
  def subtract(a: T, b: T): Double
  def add(a: T, d: Double): T
}
Run Code Online (Sandbox Code Playgroud)

您现在可以NiceProperties为Timestamps,Dates,... 创建隐式对象或val.

object BetterTimestamp extends NiceProperties[Timestamp] {
  def subtract(a: Timestamp, b: Timestamp): Double = ???
  def add(a: Timestamp, d: Double): Timestamp = ???
}
Run Code Online (Sandbox Code Playgroud)

在您的示例方法中,您将请求一个隐含NiceProperties[T]的操作,为您执行操作.

def myUtil[T](t: T)(implicit prop: NiceProperties[T]): T = {
  prop.add(prop.add(t, 1.0), 1.0)
}
Run Code Online (Sandbox Code Playgroud)

由于这是丑陋的,你可以使用一个隐含类的添加+,-......运营商的任何类,其中隐式NiceProperties[T]可供选择:

implicit class NicePropertiesOps[T](t: T)(implicit prop: NiceProperties[T]) {
  def +(d: Double): T = prop.add(t, d)
  def -(b: T): Double = prop.subtract(t, b)
}
Run Code Online (Sandbox Code Playgroud)

现在你上面的例子应该像你描述的那样工作.

def myUtil[T : NiceProperties](t: T): T = {
  (t + 1.0) + 1.0
}
Run Code Online (Sandbox Code Playgroud)

https://scastie.scala-lang.org/0D1Y9sE5S5mrzm9coZPMWw

  • 应该注意的是,这是[类型类型](https://blog.scalac.io/2017/04/19/typeclasses-in-scala.html). (2认同)