Сопоставленные типы в Scala - PullRequest
5 голосов
/ 16 апреля 2019

Есть ли способ получить тип из существующего в Scala?

Например, для case class Person(name: String, age: Int) Я хотел бы получить Product / Tuple из (Option[String], Option[Int]),то есть тип, сопоставленный с существующим.

В Typescript есть функция ( сопоставленные типы ), которая позволяет это относительно легко, и именно так я начал размышлять по этому пути.Но я не уверен, как это будет сделано в Scala.

Мне кажется, что решение предполагает использование бесформенного каким-то образом, но я не уверен, как туда добраться.

Ответы [ 2 ]

9 голосов
/ 16 апреля 2019

Я бы предложил параметризовать тип следующим образом:

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

7 голосов
/ 16 апреля 2019

С Shapeless вы можете определить тип класса

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])]
...