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

时间:2011-03-05 15:59:26

标签: scala dependency-injection lift implicit-conversion

有没有办法使这项工作(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 [T]到T的转换,范围内的Container [U]的隐式实例和一个带隐式参数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

任何提示?

2 个答案:

答案 0 :(得分:5)

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

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

在这种情况下,编译器会尝试为B的第一个隐式参数找到一些隐式f,并找到aToB。比编译器关系满足aToB的要求(implicit a: A)并找到你的implicit val a

答案 1 :(得分:1)

这可能不是解决此问题的最佳和最简洁的解决方案。但对我而言,从技术上讲是否有可能达到你想要的效果对我来说很有趣。我尝试在没有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

...不确定它是否适用于你的升降机外壳。