Scala中的映射类型

Ala*_*mas 5 generics scala shapeless

有没有一种方法可以从Scala中的现有类型派生类型?

例如,case class Person(name: String, age: Int)我想获得一个Product/ Tuple(Option[String], Option[Int]),即从现有的一种类型的映射。

Typescript(映射类型)中有一个功能可以相对轻松地实现这一点,这就是我开始思考这条道路的方式。但是我不确定如何在Scala中完成这样的事情。

我觉得解决方案涉及以某种方式使用无形状,但我不确定如何到达那里。

Som*_*ame 9

我建议如下参数化类型:

case class Person[F[_]](name: F[String], age: F[Int])
Run Code Online (Sandbox Code Playgroud)

然后您可以派生所需的类型,例如

import cats.Id

type IdPerson = Person[Id]
type OptPerson = Person[Option]
Run Code Online (Sandbox Code Playgroud)

在哪里cats.Id简单地定义为type Id[A] = A。编写自己的代码很简单,但是我建议使用cats的代码,因为它附带了有用的typeclass实例。

  • 谢谢你的回答,它非常优雅和直接。我只接受另一个,因为它不涉及更改原始案例类。真的希望我能将两者都标记为已接受,因为它们都是针对同一问题的独特且有效的解决方案。我将尝试这两种方法,看看我喜欢/不喜欢每种方法。干杯。 (2认同)

Dmy*_*tin 7

使用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
}
Run Code Online (Sandbox Code Playgroud)

并使用它(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])]
Run Code Online (Sandbox Code Playgroud)