Есть ли способ неявного преобразования неявного параметра в Scala? - PullRequest
2 голосов
/ 05 марта 2011

Есть ли способ заставить эту работу (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 и неявно требуют его в конструкторе класса без добавления импорта после каждого значения:

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

Ух ты, еще одна проблема после предыдущей: есть преобразование из некоторого Контейнера [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 ]

5 голосов
/ 05 марта 2011

Ты почти сделал это. Вам нужно только объявить a неявное:

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

В этом случае компилятор пытается найти неявное B для первого неявного аргумента f и находит aToB. Затем компилятор свяжется для удовлетворения требования aToB (implicit a: A) и найдет ваш implicit val a.

1 голос
/ 05 марта 2011

Возможно, это не самое лучшее и краткое решение этой проблемы.Но мне было интересно, возможно ли технически добиться того, чего вы хотите.Я попытался воспроизвести все задействованные классы как можно ближе без 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.

...