Scala 3:派生类型 class 以在大小写 class 和元组类型之间进行转换
Scala 3: Deriving a typeclass for conversion between a case class and a tuple type
我知道在 Scala 3 中现在可以使用 Tuple.fromProductTyped
和 summon[Mirror.Of].fromProduct
.
在大小写 class 实例和元组之间进行转换
我希望能够定义一个类型class,它见证了案例 class T
可以使用上述方法与 (A, B)
相互转换.
我已经这样定义了类型class:
trait IsPair[T, A, B]:
def toTuple(t: T): (A, B)
def fromTuple(ab: (A, B)): T
对于任何符合条件的情况 class,我们如何推导出 IsPair
?
推导到位后,以下内容应该可以编译并且 运行 没有错误:
case class Foo(a: Int, b: String)
val fooIsPair = summon[IsPair[Foo, Int, String]]
val foo = Foo(42, "qwerty")
val tuple = (42, "qwerty")
assert(fooIsPair.toTuple(foo) == tuple)
assert(fooIsPair.fromTuple(tuple) == foo)
您可以只使用 Mirror
但将其限制为 pair-like 案例 类:
import scala.deriving.Mirror
sealed trait IsPair[T]:
type A
type B
def toTuple(t: T): (A, B)
def fromTuple(ab: (A, B)): T
object IsPair:
type Aux[T, X, Y] = IsPair[T] { type A = X; type B = Y }
inline def apply[T](using ev: IsPair[T]): ev.type = ev
given instance[T <: Product, X, Y](using
ev: Mirror.Product { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes = (X, Y) }
): IsPair[T] with
override final type A = X
override final type B = Y
override def toTuple(t: T): (X, Y) =
Tuple.fromProductTyped(t)
override def fromTuple(xy: (X, Y)): T =
ev.fromProduct(xy)
end IsPair
这样我们就可以做到:
val foo = Foo(42, "qwerty")
val tuple = (42, "qwerty")
val fooIsPair = IsPair[Foo]
assert(fooIsPair.toTuple(foo) == tuple)
assert(fooIsPair.fromTuple(tuple) == foo)
可以看到代码运行 here.
我知道在 Scala 3 中现在可以使用 Tuple.fromProductTyped
和 summon[Mirror.Of].fromProduct
.
我希望能够定义一个类型class,它见证了案例 class T
可以使用上述方法与 (A, B)
相互转换.
我已经这样定义了类型class:
trait IsPair[T, A, B]:
def toTuple(t: T): (A, B)
def fromTuple(ab: (A, B)): T
对于任何符合条件的情况 class,我们如何推导出 IsPair
?
推导到位后,以下内容应该可以编译并且 运行 没有错误:
case class Foo(a: Int, b: String)
val fooIsPair = summon[IsPair[Foo, Int, String]]
val foo = Foo(42, "qwerty")
val tuple = (42, "qwerty")
assert(fooIsPair.toTuple(foo) == tuple)
assert(fooIsPair.fromTuple(tuple) == foo)
您可以只使用 Mirror
但将其限制为 pair-like 案例 类:
import scala.deriving.Mirror
sealed trait IsPair[T]:
type A
type B
def toTuple(t: T): (A, B)
def fromTuple(ab: (A, B)): T
object IsPair:
type Aux[T, X, Y] = IsPair[T] { type A = X; type B = Y }
inline def apply[T](using ev: IsPair[T]): ev.type = ev
given instance[T <: Product, X, Y](using
ev: Mirror.Product { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes = (X, Y) }
): IsPair[T] with
override final type A = X
override final type B = Y
override def toTuple(t: T): (X, Y) =
Tuple.fromProductTyped(t)
override def fromTuple(xy: (X, Y)): T =
ev.fromProduct(xy)
end IsPair
这样我们就可以做到:
val foo = Foo(42, "qwerty")
val tuple = (42, "qwerty")
val fooIsPair = IsPair[Foo]
assert(fooIsPair.toTuple(foo) == tuple)
assert(fooIsPair.fromTuple(tuple) == foo)
可以看到代码运行 here.