Я не думаю, что вы получите именно то, что хотите, поскольку неявное разрешение Scala происходит до ввода типа (но кто знает - люди делают то, что меня удивляет в Scala все время).
(примечание к стороне: шаблон CanBuildFrom
/breakOut
поддерживает что-то похожее на то, о чем вы просите, но я не вижу способа заставить его работать в этой ситуации, поскольку тип источника ограничивает, какие экземпляры доступны .)
Существует довольно стандартное обходное решение для такого рода ситуаций, хотя и связано с использованием вспомогательного класса для аппроксимации частичного применения параметров типа. Предположим, что у вас есть достаточно простой класс типа, который улавливает логику преобразования:
import java.net.URL
import shapeless._
trait Convert[I <: HList, O <: HList] { def apply(i: I): O }
object Convert extends LowPriorityConvertInstances {
implicit val convertHNil: Convert[HNil, HNil] = new Convert[HNil, HNil] {
def apply(i: HNil): HNil = i
}
implicit def convertHConsURL[T <: HList, TO <: HList](implicit
c: Convert[T, TO]
): Convert[String :: T, URL :: TO] = new Convert[String :: T, URL :: TO] {
def apply(i: String :: T): URL :: TO = new URL(i.head) :: c(i.tail)
}
}
sealed class LowPriorityConvertInstances {
implicit def convertHCons[H, T <: HList, TO <: HList](implicit
c: Convert[T, TO]
): Convert[H :: T, H :: TO] = new Convert[H :: T, H :: TO] {
def apply(i: H :: T): H :: TO = i.head :: c(i.tail)
}
}
Теперь вы можете попробовать что-то вроде этого:
def convert[I <: HList, O <: HList](i: I)(implicit c: Convert[I, O]): O = c(i)
Но есть две проблемы. Во-первых, если вы укажете параметры типа, вы всегда получите преобразование, которое превращает каждую строку в URL-адрес. Вы можете переопределить это поведение, явно предоставляя оба параметра типа, но ugh.
Мы можем (вид) улучшить эту ситуацию с вспомогательным классом:
class PartiallyAppliedConvert[O <: HList] {
def apply[I <: HList](i: I)(implicit c: Convert[I, O]): O = c(i)
}
def convert[O <: HList]: PartiallyAppliedConvert[O] =
new PartiallyAppliedConvert[O]
Теперь вы можете написать следующее:
scala> val mapped = convert[String :: URL :: HNil](list)
mapped: shapeless.::[String,shapeless.::[java.net.URL,shapeless.HNil]] = Stackoverflow :: https://stackoverflow.com/q :: HNil
Это не совсем то, что вы просили, но это довольно close, поскольку единственным типом, который мы должны явно указывать, является желаемый тип цели.
Это в значительной степени то, о чем я просил, я просто не знал, как будет выглядеть конец. Благодаря! –