【发布时间】:2017-12-30 00:05:21
【问题描述】:
我有一个关于隐式解析的问题。 说,我有以下类型类:
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 的路径上有中间 Foo,我希望能够获得 Foo[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 不是 test.Foo[test.C.type,test.A.type] 的有效隐式值,因为:hasMatchingSymbol 报告错误:类型 test.Foo[test. C.type,Mid] 从对象 Base 中的方法 transitiveFoo 开始
类型 test.Foo[test.A.type,Mid] 的发散隐式扩展从对象 Base 中的方法 transitiveFoo 开始
没有足够的方法参数隐式:(隐式 e:test.Foo[test.D.type,test.A.type])test.Foo[test.D.type,test.A.type]。未指定值参数e。
完整的日志有点长。
什么是正确的方法,给定Foo[X,Y],得到Foo[Y,X],给定Foo[X,Y]和Foo[Y,Z],得到Foo[X,Z]对于已定义的 Foo 的任何组合? 像无形的“懒惰”这样的东西在这里有帮助吗?提前致谢!
【问题讨论】:
-
亲爱的@Max,您已经有一段时间没有提出您的问题了,但是如果您有时间可以检查一下我的answer 是否正常?谢谢。
-
@DmytroMitin,非常感谢!我会尽快检查您的解决方案。并给你我的反馈。
-
您有时间检查吗? :)
-
@DmytroMitin,抱歉回答迟了。现在我已经测试了你的解决方案,它似乎工作得很好!我曾怀疑它需要使用 shapeless.Lazy 但不知道该放在哪里。所以,再次感谢你 :) 我将你的答案标记为已接受。