sách gpt4 ai đã đi

scala - 如何定义一个 HList 类型,但基于另一个 HList 类型

In lại 作者:行者123 更新时间:2023-12-04 08:27:14 31 4
mua khóa gpt4 Nike

假设我有一个案例类:

case class Foo(num: Int, str: String, bool: Boolean)
现在我还有一个简单的包装器:
sealed trait Wrapper[T]
case class Wrapped[T](value: T) extends Wrapper[T]
(以及其他一些在这里不重要的 Wrapper 实现)
我可以使用 Generic[Foo] 来获取代表这个案例类的 Aux: val genFoo = Generic[Foo](在我的真实代码中,我使用 LabelledGeneric 以免丢失字段名称)
这为我提供了一个表示 HList 定义的类型:
Generic.Aux[Foo, Int :: String :: Boolean :: HNil]
(当与 LabelledGeneric 一起使用时,定义要复杂得多,但本质上是一样的)
现在我想为 HList 创建一个类型定义,而不是原始类型,而是包含包装类型。例子:
type WrappedHlist = Wrapper[Int] :: Wrapper[String] :: Wrapper[Boolean] :: HNil
然后我可以使用这个类型定义来生成一个 Circe 编码器/解码器(我已经为 Wrapper 类型提供了必要的编码器/解码器)。
所有必要的信息都在编译时存在,因为第二个 HList 的定义很容易从第一个确定。现在,我可以通过手动写出定义来实现这一点,或者通过使用冗余版本重复案例类 Foo 的定义,其中所有内容都定义为 Wrappers。如何创建不需要我重复所有内容的定义?

1 Câu trả lời

嗯,这可以通过一些类型类、依赖路径的类型和 Aux 模式来实现:

trait WrapperHelper[In] {
type Out
def wrap(i: In): Out
}
object WrapperHelper {
type Aux[I, O] = WrapperHelper[I] { type Out = O }

implicit val nilWH: WrapperHelper.Aux[HNil, HNil] = new WrapperHelper[HNil] {
type Out = HNil
def wrap(i: HNil): HNil = i
}

implicit def hconsWH[H, TI <: HList, TO <: HList](
implicit
tailWH: WrapperHelper.Aux[TI, TO]
): WrapperHelper.Aux[H :: TI, Wrapper[H] :: TO] = new WrapperHelper[H :: TI] {
type Out = Wrapper[H] :: TO
def wrap(i: H :: TI): Wrapper[H] :: TO = i match {
case head :: tail => Wrapped(head) :: tailWH.wrap(tail)
}
}
}

def wrap[I](i: I)(implicit wh: WrapperHelper[I]): wh.Out = wh.wrap(i)
HNIl 被视为一种特殊情况,其中 In = Out。对于其他一切……您仍然必须递归地映射类型。虽然不漂亮,但这应该做你想做的:
@ wrap(Generic[Foo].to(Foo(1, "", true)))
res7: Wrapper[Int] :: Wrapper[String] :: Wrapper[Boolean] :: HNil = Wrapped(1) :: Wrapped("") :: Wrapped(true) :: HNil
假设您想提供一些自定义编码/解码逻辑,您应该修改签名
implicit def hconsWH[H, TI <: HList, TO <: HList](
implicit
tailWH: WrapperHelper.Aux[TI, TO]
): WrapperHelper.Aux[H :: TI, Wrapper[H] :: TO]
implicit def hconsWH[H, TI <: HList, TO <: HList](
implicit
thatThingINeedToLiftAToWrapperA: Encoder[A], // whatever is needed to lift A => Wrapper[A]
tailWH: WrapperHelper.Aux[TI, TO]
): WrapperHelper.Aux[H :: TI, Wrapper[H] :: TO]
即使您不需要实现,在这里定义 typeclass 仍然很有用,只是为了提供一些可以为您解析类型的隐式证据。

关于scala - 如何定义一个 HList 类型,但基于另一个 HList 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65201029/

31 4 0
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com