Is there a way to implicitly convert an implicit parameter to 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 related to injection of Lift (2.2) dependencies, I try to convert Vendor [T] to T and implicitly require it in the class constructor without adding import 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 is UserStore :

 class UserStore(implicit db: DbAccess) 

Am I doing something wrong?

UPDATE

Thanks to Easy Angel for answering the first part. But this does not solve the Lift DI problem, because it turns out that in the scope there is an opposite transformation (from T to Vendor [T]), and both of these lead to an error: implicit extension diverges.

Can this be solved?

UPDATE2

Another problem after the previous one: the presence of a transformation from some container [T] to T with an implicit instance of the container [U] in scope, and a function with an implicit parameter U also leads to a β€œvague implicit extension”:

 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]) = vv f 

Any clues?

+2
source share
2 answers

You almost did it. You need to declare a implicit:

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

In this case, the compiler tries to find the implicit B for the first implicit argument f and finds aToB . Then the compiler satisfies the requirements of aToB ( implicit a: A ) and finds your implicit val a .

+5
source

This is probably not the best and shortest solution to this problem. But I was wondering if you can technically achieve what you want. I tried to reproduce all the classes involved as close to the elevator as possible ... and here is one of the possible solutions using view boundaries:

 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 the fact that T not DbAccess , but it also knows that T can be viewed and used as T


Edit

About your second example (in the 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 if it will work in your Lift case.

+1
source

Source: https://habr.com/ru/post/1343384/


All Articles