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