如何在Scala中链接隐式函数? [英] How can I chain implicits in Scala?

查看:77
本文介绍了如何在Scala中链接隐式函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

pimp-my-library模式允许我通过在类中隐式转换为实现该方法的隐式转换,从而在类中似乎添加了一种方法.

The pimp-my-library pattern allows me to seemingly add a method to a class by making available an implicit conversion from that class to one that implements the method.

Scala不允许进行两次这样的隐式转换,所以我无法使用隐式AB以及另一个隐式BCAC.有没有办法解决这个限制?

Scala does not allow two such implicit conversions taking place, however, so I cannot got from A to C using an implicit A to B and another implicit B to C. Is there a way around this restriction?

推荐答案

Scala限制了自动转换以添加方法,这是因为它在尝试查找方法时不会应用多个转换.例如:

Scala has a restriction on automatic conversions to add a method, which is that it won't apply more than one conversion in trying to find methods. For example:

class A(val n: Int)
class B(val m: Int, val n: Int)
class C(val m: Int, val n: Int, val o: Int) {
  def total = m + n + o
}

// This demonstrates implicit conversion chaining restrictions
object T1 { // to make it easy to test on REPL
  implicit def toA(n: Int): A = new A(n)
  implicit def aToB(a: A): B = new B(a.n, a.n)
  implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n)

  // won't work
  println(5.total)
  println(new A(5).total)

  // works
  println(new B(5, 5).total)
  println(new C(5, 5, 10).total)
}

自Scala 2.11 https://issues.scala-lang.org/browse/SI-7629 (您可以改用类型类)

View bounds ('<%') are deprecated since Scala 2.11 https://issues.scala-lang.org/browse/SI-7629 (You can use type classes instead)

但是,如果隐式定义本身需要一个隐式参数(View绑定),则Scala 查找所需的其他隐式值.从上一个示例继续:

However, if an implicit definition requires an implicit parameter itself(View bound), Scala will look for additional implicit values for as long as needed. Continue from the last example:

// def m[A <% B](m: A) is the same thing as
// def m[A](m: A)(implicit ev: A => B)

object T2 {
  implicit def toA(n: Int): A = new A(n)
  implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
  implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)

  // works
  println(5.total)
  println(new A(5).total)
  println(new B(5, 5).total)
  println(new C(5, 5, 10).total)
}

魔术!",您可能会说.不是这样这是编译器如何翻译每个译本的方法:

"Magic!", you might say. Not so. Here is how the compiler would translate each one:

object T1Translated {
  implicit def toA(n: Int): A = new A(n)
  implicit def aToB(a: A): B = new B(a.n, a.n)
  implicit def bToC(b: B): C = new C(b.m, b.n, b.m + b.n)

  // Scala won't do this
  println(bToC(aToB(toA(5))).total)
  println(bToC(aToB(new A(5))).total)

  // Just this
  println(bToC(new B(5, 5)).total)

  // No implicits required
  println(new C(5, 5, 10).total)
}

object T2Translated {
  implicit def toA(n: Int): A = new A(n)
  implicit def aToB[A1 <% A](a: A1): B = new B(a.n, a.n)
  implicit def bToC[B1 <% B](b: B1): C = new C(b.m, b.n, b.m + b.n)

  // Scala does this
  println(bToC(5)(x => aToB(x)(y => toA(y))).total)
  println(bToC(new A(5))(x => aToB(x)(identity)).total)      
  println(bToC(new B(5, 5))(identity).total)

  // no implicits required
  println(new C(5, 5, 10).total)
}

因此,当bToC被用作隐式转换时,aToBtoA被作为隐式参数传递,而不是被链接为隐式转换.

So, while bToC is being used as an implicit conversion, aToB and toA are being passed as implicit parameters, instead of being chained as implicit conversions.

编辑

相关的感兴趣的问题:

这篇关于如何在Scala中链接隐式函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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