Да, есть. Позвольте мне привести более простой пример. Я надеюсь, что это также будет работать с
Ваш более сложный вариант использования.
скажем, у нас есть
trait Foo[A]
class Bar {
def methWithImplicits[A,B](f: A => B)(implicit foo: Foo[A]) = null
}
implicit def fooInt: Foo[Int] = null
Теперь это именно та проблема, которую вы описываете, поскольку
(new Bar).methWithImplicits(x => x)
дает "пропущенный тип параметра".
Итак, что мы хотели бы сделать, это переместить неявный параметр «за»
явно предоставленная функция, так что Scala видит неявное first . Что ж,
Один из способов сделать это - добавить дополнительный слой косвенности:
class Bar {
def methWithImplicits2[A](implicit foo: Foo[A]) = new {
def apply[B](f: A => B) = null
}
}
(new Bar).methWithImplicits2.apply(x => x)
Это работает, хотя синтаксис не такой красивый. Один из способов вы могли бы рассмотреть
Синтаксис заключается в том, чтобы взглянуть на ваш текущий дизайн и посмотреть, сможете ли вы подкрасться
неявное в любой из «более ранних» стадий. Например, так как
mapValuesStrict
метод имеет смысл только тогда, когда неявное было
при условии, что вы можете сделать неявное свойство объекта вместо
перешел к методу.
Но если это не удобно в вашем дизайне, вы можете использовать дополнительное неявное
преобразование, чтобы прокрасться назад. Вот что мы хотели бы сделать:
implicit def addFoo[A](bar: Bar)(implicit foo: Foo[A]) = new {
def methWithImplicits3[B](f: A => B) = null
}
Но, к сожалению, я подозреваю, что есть ошибка в Scala, которая приводит к
поиск неявного значения, которое является слишком полиморфным, заставляя его жаловаться:
could not find implicit value for parameter foo: test.Foo[A]
Это происходит только при использовании неявных преобразований, поэтому я думаю, что это
ошибка. Таким образом, мы можем взять его на назад еще дальше: (и, требуя -Xexperimental
для зависимых типов методов):
trait FooWrapper {
type AA
val foo: Foo[AA]
}
implicit def wrapFoo[A](implicit theFoo: Foo[A]) = new FooWrapper {
type AA = A
val foo = theFoo
}
implicit def addFoo(bar: Bar)(implicit foo: FooWrapper) = new {
def methWithImplicits3[B](f: foo.AA => B) = null
}
А теперь
(new Bar).methWithImplicits3(x => x)
отлично работает;)
Обновление
В вашем конкретном случае, я думаю, вам лучше всего включить неявное в enhanceGenTraversable
, хотя, увы, для обхода возможной ошибки требуется такой же взлом:
// Notice `ev` is now a field of the class
class EnhancedGenTraversableLike[A, Repr <: GenTraversable[A], T, U]
(self: GenTraversableLike[A, Repr], ev: A <:< (T, U))
{
def mapValuesStrict[R, That](f: U => R)(implicit bf: CanBuildFrom[Repr, (T, R), That]) = {
val b = bf(self.asInstanceOf[Repr])
b.sizeHint(self.size)
for ((k: T, v: U) <- self) b += k -> f(v)
b.result
}
}
// The Hack
trait WrappedPairBound[A] {
type TT
type UU
val bound: A <:< (TT, UU)
}
implicit def wrapPairBound[A,T,U](implicit ev: A <:< (T,U)) = new WrappedPairBound[A] {
type TT = T
type UU = U
val bound = ev
}
// Take the implicit here
implicit def enhanceGenTraversableLike[A, Repr <: GenTraversable[A]]
(self: GenTraversableLike[A, Repr])(implicit ev: WrappedPairBound[A]) =
new EnhancedGenTraversableLike[A, Repr, ev.TT, ev.UU](self, ev.bound)