微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Shapeless 中的产品上扩展 Option[_]

如何解决在 Shapeless 中的产品上扩展 Option[_]

我正在通过 Shapeless 学习我的方法,我希望实现一个特定的行为,以允许我们的代码以相同的方式扩展可选案例类,无论它们是否存在。基本上:

给定一个 Option[N] where N <: Product,我想生成一个 HList,其类型与 Generic[N].to 生成的类型相同,但每个元素都包含在 {{ 1}} 如果还没有。例如:

Option

我的最终目标是能够展平嵌套的 case 类,因此我想将此作为规则引入,以便 Shapeless 可以通过类型推断自动执行此操作。我心中最大的障碍是理解如何编写 case class Foo(a: String,b: Option[Long],c: Option[String]) optionalize[Foo](Some(Foo("abc",Some(123L),None))) // => Some("abc") :: Some(123L) :: None :: HNil optionalize[Foo](None) // => None :: None :: None :: HNil // where optionalize.Out = Option[String] :: Option[Long] :: Option[String] :: HNil 案例。目前,我的代码如下所示:

None

为了写出 trait LowPriEnsureOptional extends poly1 { implicit def somethingCase[In]: Case.Aux[In,Option[In]] = at(thing => Some(thing)) implicit val hnilCase: Case.Aux[HNil,HNil] = at(identity) } object EnsureOptional extends LowPriEnsureOptional { implicit def optionCase[In <: Option[_]]: Case.Aux[In,In] = at(identity) } object OptionizeHlist { def optionizeCaseClass[ CC <: Product,R <: HList ](occ: Option[CC])( implicit gen: Generic[CC] { type Repr = R },optionalize: Mapper[EnsureOptional.type,R] ): optionalize.Out = occ match { case Some(cc) => optionalize.apply(gen.to(cc)) case None => ??? } } 案例,我需要一些方法,在给定案例类的情况下,获取其通用表示,通过 None 运行它,并生成一个完全由 {{ 1}}s,但我不知道从哪里开始。

解决方法

请注意,如果您被传递了一个 None,则输入erasure 会使您无法知道将多少个None 放入输出列表。因此,您需要另一个隐式参数来将该信息保留到运行时。

final class AllNoneable[H <: HList] private (val allNone: H) extends AnyVal
object AllNoneable {
    implicit val allNoneableHNil = new AllNoneable[HNil](HNil)
    implicit def allNoneableCons[H >: None.type,T <: HList](implicit t: AllNoneable[T])
    = new AllNoneable[H :: T](None :: t.allNone)
}

此外,hnilCase 什么也不做。

trait LowPriEnsureOptional extends Poly1 {
  implicit def somethingCase[In]: Case.Aux[In,Option[In]] = at(Some(_))
}
object EnsureOptional extends LowPriEnsureOptional {
  implicit def optionCase[In <: Option[_]]: Case.Aux[In,In] = at(identity)
}
def optionalizeCase
  [C,Rep <: HList,Opt <: HList](c: Option[C])
  (implicit
    gen: Generic.Aux[C,Rep],opt: Mapper.Aux[EnsureOptional.type,Rep,Opt],nones: AllNoneable[Opt]): Opt
= c match {
    case Some(c) => opt.apply(gen.to(c))
    case None => nones.allNone
}

Scastie

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。