如何在Scala中链接隐式函数? [英] How can I chain implicits in 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不允许进行两次这样的隐式转换,所以我无法使用隐式A
到B
以及另一个隐式B
到C
从A
到C
.有没有办法解决这个限制?
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
被用作隐式转换时,aToB
和toA
被作为隐式参数传递,而不是被链接为隐式转换.
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屋!