Scala 中的映射类型
Mapped types in Scala
有没有办法从 Scala 中的现有类型派生类型?
例如,对于 case class Person(name: String, age: Int)
,我想获得 (Option[String], Option[Int])
的 Product
/Tuple
,即从现有类型映射而来的类型。
Typescript (mapped types) 中有一个功能可以相对轻松地实现这一点,这就是我开始思考这条道路的方式。但是我不确定在 Scala 中如何完成这样的事情。
我觉得解决方案涉及以某种方式使用 shapeless,但我不确定如何实现。
我建议按如下方式参数化类型:
case class Person[F[_]](name: F[String], age: F[Int])
然后你可以导出你想要的类型,比如
import cats.Id
type IdPerson = Person[Id]
type OptPerson = Person[Option]
其中 cats.Id
简单定义为类型 Id[A] = A
。自己编写很简单,但我建议使用 cat 的,因为它带有有用的类型类实例。
使用 Shapeless 你可以定义类型 class
import shapeless.ops.{hlist, product, tuple}
import shapeless.poly.~>
import shapeless.{Generic, HList, Id, the}
trait Partial[A] {
type Out
}
object Partial {
type Aux[A, Out0] = Partial[A] { type Out = Out0 }
object optionPoly extends (Id ~> Option) {
override def apply[T](t: T): Option[T] = null
}
// implicit def mkPartial[A, L <: HList, L1 <: HList](implicit
// generic: Generic.Aux[A, L],
// mapper: hlist.Mapper.Aux[optionPoly.type, L, L1],
// tupler: hlist.Tupler[L1]): Aux[A, tupler.Out] = null
implicit def mkPartial[A, T](implicit
toTuple: product.ToTuple.Aux[A, T],
mapper: tuple.Mapper[T, optionPoly.type],
): Aux[A, mapper.Out] = null
}
并使用它(the
是implicitly
的改进版本)
case class Person(name: String, age: Int)
// val pp = the[Partial[Person]]
// type PersonPartial = pp.Out
type PersonPartial = the.`Partial[Person]`.Out
implicitly[PersonPartial =:= (Option[String], Option[Int])]
有没有办法从 Scala 中的现有类型派生类型?
例如,对于 case class Person(name: String, age: Int)
,我想获得 (Option[String], Option[Int])
的 Product
/Tuple
,即从现有类型映射而来的类型。
Typescript (mapped types) 中有一个功能可以相对轻松地实现这一点,这就是我开始思考这条道路的方式。但是我不确定在 Scala 中如何完成这样的事情。
我觉得解决方案涉及以某种方式使用 shapeless,但我不确定如何实现。
我建议按如下方式参数化类型:
case class Person[F[_]](name: F[String], age: F[Int])
然后你可以导出你想要的类型,比如
import cats.Id
type IdPerson = Person[Id]
type OptPerson = Person[Option]
其中 cats.Id
简单定义为类型 Id[A] = A
。自己编写很简单,但我建议使用 cat 的,因为它带有有用的类型类实例。
使用 Shapeless 你可以定义类型 class
import shapeless.ops.{hlist, product, tuple}
import shapeless.poly.~>
import shapeless.{Generic, HList, Id, the}
trait Partial[A] {
type Out
}
object Partial {
type Aux[A, Out0] = Partial[A] { type Out = Out0 }
object optionPoly extends (Id ~> Option) {
override def apply[T](t: T): Option[T] = null
}
// implicit def mkPartial[A, L <: HList, L1 <: HList](implicit
// generic: Generic.Aux[A, L],
// mapper: hlist.Mapper.Aux[optionPoly.type, L, L1],
// tupler: hlist.Tupler[L1]): Aux[A, tupler.Out] = null
implicit def mkPartial[A, T](implicit
toTuple: product.ToTuple.Aux[A, T],
mapper: tuple.Mapper[T, optionPoly.type],
): Aux[A, mapper.Out] = null
}
并使用它(the
是implicitly
的改进版本)
case class Person(name: String, age: Int)
// val pp = the[Partial[Person]]
// type PersonPartial = pp.Out
type PersonPartial = the.`Partial[Person]`.Out
implicitly[PersonPartial =:= (Option[String], Option[Int])]