Scala 有没有办法隐式转换隐式参数?

发布于 2024-10-20 08:06:23 字数 1278 浏览 6 评论 0原文

有没有办法让这个工作(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

耳钉梦 2024-10-27 08:06:24

这可能不是这个问题的最佳和最简洁的解决方案。但对我来说很有趣的是技术上是否可以实现你想要的。我尝试在不使用 Lift 的情况下尽可能地重现所有涉及的类...这是使用视图边界的可能解决方案之一:

class DbAccess
class UserStore[T](implicit db: T, ev: T => DbAccess)

class Vendor[T] (val vend: T)
class FactoryMaker[T] (vend: T) extends Vendor[T](vend)

implicit def vendorToVal[T](vendor: Vendor[T]) = vendor.vend

implicit val db: Vendor[DbAccess] = new FactoryMaker[DbAccess](new DbAccess) {}
implicit val userStore = new FactoryMaker[UserStore[Vendor[DbAccess]]](new UserStore) {}

在这种情况下,UserStore 知道事实,即 T 不是 DbAccess,但它也知道 T 可以作为 T 进行查看和使用。


编辑

关于您的第二个示例(在评论中)。我想到了这个简单的解决方法:

class A
class B
trait HighPrio

def f(implicit b: B) {}

implicit val a = new A with HighPrio

implicit def aToB(implicit a: A with HighPrio) = new B;
implicit def bToA(implicit b: B) = new A;

f

...不确定它是否适用于您的 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:

class DbAccess
class UserStore[T](implicit db: T, ev: T => DbAccess)

class Vendor[T] (val vend: T)
class FactoryMaker[T] (vend: T) extends Vendor[T](vend)

implicit def vendorToVal[T](vendor: Vendor[T]) = vendor.vend

implicit val db: Vendor[DbAccess] = new FactoryMaker[DbAccess](new DbAccess) {}
implicit val userStore = new FactoryMaker[UserStore[Vendor[DbAccess]]](new UserStore) {}

In this case UserStore knows fact, that T is not DbAccess, but it also knows that T can be viewed and used as T.


Edit

About your second example (in comment). This simple workaround comes to my mind:

class A
class B
trait HighPrio

def f(implicit b: B) {}

implicit val a = new A with HighPrio

implicit def aToB(implicit a: A with HighPrio) = new B;
implicit def bToA(implicit b: B) = new A;

f

... not sure whether it will work in your Lift case.

z祗昰~ 2024-10-27 08:06:23

你几乎成功了。您只需要声明 a 隐式:

implicit def aToB(implicit a: A) = new B

在这种情况下,编译器尝试为 f 的第一个隐式参数找到一些隐式 B ,并且它找到 <代码>aToB。编译器会满足 aToB 的要求(隐式 a: A)并找到您的隐式 val a

You almost made it. You only need to declare a implicit:

implicit def aToB(implicit a: A) = new B

In this case compiler tries to find some implicit B for the first implicit argument of f and it finds aToB. Than compiler ties to satisfy aToB's requirement (implicit a: A) and finds your implicit val a.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文