Хотя на самом деле это невозможно с собственным scala без shapeless
или макросом на уровне типа в scala 2. *, возможно создать функцию, которая отображает значение типа a на значение типа b. Одна вещь, которую вы должны сделать, это определить класс типов trait LiftFoo[T]
, который имеет единственный метод def lift[T](t: T)(implicit instance: LiftFoo[T]): Foo[T]
, и создать реализации для всех типов, которые вы когда-либо захотите.
Затем вы можете отобразить свой кортеж с помощью полифункции:
object Bla{
import shapeless.syntax.std.tuple._
import shapeless.syntax._
import shapeless.poly._
case class Foo[T](t: T)
trait LiftFoo[T] {
def liftImpl(t: T): Foo[T]
}
object LiftFoo {
def lift[T](t: T)(implicit instance: LiftFoo[T]): Foo[T] = instance.liftImpl(t)
}
implicit val liftInt: LiftFoo[Int] = {Foo(_)}
implicit val liftString: LiftFoo[String] = {Foo(_)}
implicit val liftDouble: LiftFoo[Double] = {Foo(_)}
val a: (Int, Int, String, Double) = ???
object LiftFooPoly extends Poly1 {
implicit def onLiftable[T: LiftFoo] = at[T](LiftFoo.lift[T])
}
val b = a.map{LiftFooPoly}
}
Однако, scala 3 (т.е. Dotty) позволит сделать это на уровне типа с лямбдами типа и типами соответствия . Typelambda позволяет использовать типы форм type LiftFoo[T] = [T] =>> Foo[T]
и сопоставлять типы и кортежи в scala 3, теперь повторно составляя HList, и вы можете рекурсивно перемещаться по его элементам с помощью типов совпадений :
type TupleLiftFoo[Xs <: Tuple] <: Tuple = Xs match
case Unit => Unit
case x *: xs => LiftFoo[x] *: TupleLiftFoo[xs]