开发者

Is there a way to implicitly convert an implicit parameter in Scala?

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 vendorT开发者_运维技巧oVal[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?


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜