发散隐式扩展
我有一个关于隐含解析的问题。 说,我有以下类型的类:发散隐式扩展
trait Foo[In <: Base, Out <: Base] {
def factor : Double
}
而
sealed trait Base
object Base {
implicit def symmetricFoo[In <: Base, Out <: Base](implicit foo : Foo[In, Out]) : Foo[Out, In] =
new Foo[Out, In] {
def factor : Double = 1.0/foo.factor
}
implicit def transitiveFoo[In <: Base, Mid <: Base, Out <: Base](implicit foo1 : Foo[In, Mid], foo2 : Foo[Mid, Out]) : Foo[In, Out] =
new Foo[In, Out] {
def factor : Double = foo1.factor * foo2.factor
}
}
case object A extends Base
case object B extends Base {
implicit def bFoo : Foo[B.type, A.type] =
new Foo[B.type, A.type] {
def factor : Double = 2.0
}
}
case object C extends Base {
implicit def cFoo : Foo[C.type, A.type] =
new Foo[C.type, A.type] {
def factor : Double = 3.0
}
}
case object D extends Base {
implicit def dFoo : Foo[D.type, C.type] =
new Foo[D.type, C.type] {
def factor : Double = 5.0
}
}
我希望能够得到,如果我有沿路径中介富的富[X,Y]的情况下, X到Y.有时它确实有效,例如, G。
println(implicitly[Foo[D.type, A.type]].factor) // 15.0 (D->C, C->A = 5 * 3)
println(implicitly[Foo[D.type, B.type]].factor) // 7.5 (D->C, C->A, A->B = 5 * 3 * 1/2)
,但如果我改变行的顺序,它不会:
println(implicitly[Foo[D.type, B.type]].factor) // 7.5
println(implicitly[Foo[D.type, A.type]].factor) // does not compile
有很多或多或少相同的错误消息像
test.this.Base.transitiveFoo is not a valid implicit value for test.Foo[test.C.type,test.A.type] because: hasMatchingSymbol reported error: diverging implicit expansion for type test.Foo[test.C.type,Mid] starting with method transitiveFoo in object Base
diverging implicit expansion for type test.Foo[test.A.type,Mid] starting with method transitiveFoo in object Base
not enough arguments for method implicitly: (implicit e: test.Foo[test.D.type,test.A.type])test.Foo[test.D.type,test.A.type]. Unspecified value parameter e.
完整的日志有点长。
给出Foo [X,Y]得到Foo [Y,X],给出Foo [X,Y]和Foo [Y,Z]得到Foo [X,Z]的正确方法是什么]为定义的Foo的任何组合? 会像没形状的'懒惰的帮助在这里?提前致谢!
这种变异似乎工作:
import shapeless.Lazy
trait Foo[In <: Base, Out <: Base] {
def factor : Double
}
sealed trait Base
case object A extends Base
case object B extends Base
case object C extends Base
case object D extends Base
trait LowPriorityImplicits {
implicit def symmetricFoo[In <: Base, Out <: Base](implicit foo : Lazy[Foo[In, Out]]) : Foo[Out, In] =
new Foo[Out, In] {
def factor : Double = 1.0/foo.value.factor
}
}
object Base extends LowPriorityImplicits {
implicit def bFoo : Foo[B.type, A.type] =
new Foo[B.type, A.type] {
def factor : Double = 2.0
}
implicit def cFoo : Foo[C.type, A.type] =
new Foo[C.type, A.type] {
def factor : Double = 3.0
}
implicit def dFoo : Foo[D.type, C.type] =
new Foo[D.type, C.type] {
def factor : Double = 5.0
}
implicit def transitiveFoo[In <: Base, Out <: Base, Mid <: Base](implicit foo1 : Foo[In, Mid], foo2 : Foo[Mid, Out]) : Foo[In, Out] =
new Foo[In, Out] {
def factor : Double = foo1.factor * foo2.factor
}
}
def main(args: Array[String]): Unit = {
println(implicitly[Foo[D.type, B.type]].factor)
println(implicitly[Foo[D.type, A.type]].factor)
}
7.5
15.0
def main(args: Array[String]): Unit = {
println(implicitly[Foo[D.type, A.type]].factor)
println(implicitly[Foo[D.type, B.type]].factor)
}
15.0
7.5
以防万一我build.sbt:
scalaOrganization := "org.typelevel"
scalaVersion := "2.12.3-bin-typelevel-4"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2"
亲爱@Max,它已经有一段时间,因为你问你的问题,但如果你有一个时刻你可以检查我的[答案](https://stackoverflow.com/a/45924188/5249621)是否可以?谢谢。 –
@DmytroMitin,非常感谢!我会检查你的解决方案a.s.a.p.并给你我的反馈。 – Max
你有时间检查吗? :) –