Scala 有没有办法隐式转换隐式参数?
有没有办法让这个工作(Scala 2.8.1):
class A
class B
def f(implicit b: B) {}
implicit val a = new A
implicit def aToB(a: A) = new B
f(a) // works ok
f // error: could not find implicit value for parameter b: B
实际上我的问题是 Lift 的(2.2)依赖注入,我试图将 Vendor[T] 转换为 T 并在类构造函数中隐式需要它而不添加导入在每个 val 之后:
object DependencyFactory extends Factory {
implicit def vendorToVal[T](vendor: Vendor[T]): T = vendor.vend
implicit val db = new FactoryMaker[DbAccess](Model) {}
//uncommenting the following line makes it work, but can we avoid it?
//import db._
implicit val userStore = new FactoryMaker[UserStore](new UserStore) {}
}
UserStore
是:
class UserStore(implicit db: DbAccess)
我做错了什么吗?
更新
感谢Easy Angel回答第一部分。但它并没有解决我的 Lift DI 问题,因为事实证明,范围内存在相反的转换(从 T 到 Vendor[T]),并且这两者都会导致“错误:发散隐式扩展”。
能解决吗?
UPDATE2
哇,继上一个之后又出现了一个问题:在范围内使用 Container[U] 的隐式实例从某个 Container[T] 到 T 的转换以及具有隐式参数 U 的函数会导致“发散隐式扩展”太:
class A
case class Vendor[T](v: T)
def f(implicit a: A) {}
implicit val vendor = Vendor(new A)
implicit def vendorToVal[T](implicit v: Vendor[T]) = v.v
f
有什么提示吗?
Is there a way to make this work (Scala 2.8.1):
class A
class B
def f(implicit b: B) {}
implicit val a = new A
implicit def aToB(a: A) = new B
f(a) // works ok
f // error: could not find implicit value for parameter b: B
Actually my problem is with Lift's (2.2) dependency injection, i'm trying to convert Vendor[T] to T and implicitly require it in a class constructor without adding imports after each val:
object DependencyFactory extends Factory {
implicit def vendorToVal[T](vendor: Vendor[T]): T = vendor.vend
implicit val db = new FactoryMaker[DbAccess](Model) {}
//uncommenting the following line makes it work, but can we avoid it?
//import db._
implicit val userStore = new FactoryMaker[UserStore](new UserStore) {}
}
Where UserStore
is:
class UserStore(implicit db: DbAccess)
Am i doing something wrong?
UPDATE
Thanks to Easy Angel for answering the first part. But it doesn't solve my Lift DI problem because it turns out that there is an opposite conversion in scope (from T to Vendor[T]) and having those both leads to 'error: diverging implicit expansion'.
Can it be solved?
UPDATE2
Wow one more problem after previous: having a conversion from some Container[T] to T with implicit instance of Container[U] in scope and a function with implicit parameter U leads to 'diverging implicit expansion' too:
class A
case class Vendor[T](v: T)
def f(implicit a: A) {}
implicit val vendor = Vendor(new A)
implicit def vendorToVal[T](implicit v: Vendor[T]) = v.v
f
Any hints?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能不是这个问题的最佳和最简洁的解决方案。但对我来说很有趣的是技术上是否可以实现你想要的。我尝试在不使用 Lift 的情况下尽可能地重现所有涉及的类...这是使用视图边界的可能解决方案之一:
在这种情况下,
UserStore
知道事实,即T
不是DbAccess
,但它也知道T
可以作为T
进行查看和使用。编辑
关于您的第二个示例(在评论中)。我想到了这个简单的解决方法:
...不确定它是否适用于您的 Lift 案例。
This is probably not the best and most concise solution to this problem. But it was interesting for me whether it's technically possible to achieve what you want. I tried to reproduce all involved classes as close as possible without Lift... and here is one of the possible solutions using view bounds:
In this case
UserStore
knows fact, thatT
is notDbAccess
, but it also knows thatT
can be viewed and used asT
.Edit
About your second example (in comment). This simple workaround comes to my mind:
... not sure whether it will work in your Lift case.
你几乎成功了。您只需要声明
a
隐式:在这种情况下,编译器尝试为
f
的第一个隐式参数找到一些隐式B
,并且它找到 <代码>aToB。编译器会满足aToB
的要求(隐式 a: A
)并找到您的隐式 val a
。You almost made it. You only need to declare
a
implicit:In this case compiler tries to find some implicit
B
for the first implicit argument off
and it findsaToB
. Than compiler ties to satisfyaToB
's requirement (implicit a: A
) and finds yourimplicit val a
.