我有下一堂课:
case class Foo(a: Option[Int], b: Option[String], c: Option[Double])
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,所有字段都是可选的,我希望将此类转换为HList或Tuple,就像
val f1 = Foo(Some(1) , None, Some(3D))
val f2 = Foo(None, "foo")
val result1 = f1.to[Int::Double::HNil] // => 1::3D
val result2 = f2.to[String::HNil] // "foo"
Run Code Online (Sandbox Code Playgroud)
没有反思可能吗?
有可能在Shapeless中使用现有的类型类(类似于NatTRel和RemoveAll),但我不是百分之百确定,这是我只编写自己的类型类的情况:
import shapeless._
trait OptionalPieces[L <: HList, S <: HList] {
def apply(l: L): Option[S]
}
object OptionalPieces extends LowPriorityOptionalPieces {
implicit val hnilOptionalPieces: OptionalPieces[HNil, HNil] =
new OptionalPieces[HNil, HNil] {
def apply(l: HNil): Option[HNil] = Some(HNil)
}
implicit def hconsOptionalPiecesMatch[H, T <: HList, S <: HList](implicit
opt: OptionalPieces[T, S]
): OptionalPieces[Option[H] :: T, H :: S] =
new OptionalPieces[Option[H] :: T, H :: S] {
def apply(l: Option[H] :: T): Option[H :: S] = for {
h <- l.head
t <- opt(l.tail)
} yield h :: t
}
}
sealed class LowPriorityOptionalPieces {
implicit def hconsOptionalPiecesNoMatch[H, T <: HList, S <: HList](implicit
opt: OptionalPieces[T, S]
): OptionalPieces[Option[H] :: T, S] =
new OptionalPieces[Option[H] :: T, S] {
def apply(l: Option[H] :: T): Option[S] = opt(l.tail)
}
}
Run Code Online (Sandbox Code Playgroud)
该证人是L含有至少所有的元素S包裹Option,以和为您提供了一种方式在运行时(安全)解开他们.
然后我们可以定义一个语法助手类,如下所示:
implicit class OptionalPiecesSyntax[A, R <: HList](a: A)(implicit
gen: Generic.Aux[A, R]
) {
def to[S <: HList](implicit op: OptionalPieces[gen.Repr, S]): Option[S] =
op(gen.to(a))
}
Run Code Online (Sandbox Code Playgroud)
然后:
scala> val f1 = Foo(Some(1) , None, Some(3D))
f1: Foo = Foo(Some(1),None,Some(3.0))
scala> val f2 = Foo(None, Some("foo"), None)
f2: Foo = Foo(None,Some(foo),None)
scala> val result1 = f1.to[Int :: Double :: HNil]
result1: Option[shapeless.::[Int,shapeless.::[Double,shapeless.HNil]]] = Some(1 :: 3.0 :: HNil)
scala> val result2 = f2.to[String :: HNil]
result2: Option[shapeless.::[String,shapeless.HNil]] = Some(foo :: HNil)
Run Code Online (Sandbox Code Playgroud)
如果你真的想要异常,你可以只调用.get语法类,但这似乎是一个坏主意.
| 归档时间: |
|
| 查看次数: |
752 次 |
| 最近记录: |