无形过滤器选项列表
shapeless filter a list of options
我是 shapeless 的新手,尝试解决以下问题。我有不同长度的元组,其中 Option[(R[A], A)] 作为元素,我想过滤元组,以便它只产生一些。请注意,我在编译时没有 Some 或 None,只有 Option。
我想我有一种递归问题,但无法描述它。我有类似以下的想法(我已经将元组转换为 HList:
def performFinalStep[A1](t: Tuple1[A1]) = ???
def performFinalStep[A1, A2](t: Tuple2[A1, A2]) = ???
...
def reduce[T <: HList, A <: HList](l: Option[(R[A], A)] :: T, acc: A) = {
case h :: HNil => performFinalStep(toTuple(h :: acc))
case h :: t => reduce(t, h :: acc) //does not work as it is not known if T's head is Option[(R[A], A)]
}
reduce((Option(R(1), 2), Option(R("S", "s"))).productElements, HNil)
有两件事我不知道,如何将 HList 变回元组以及如何克服 T 的输入?
在 Shapeless 中,可以通过 shapeless.Generic
将 classes 转换为 HList,反之亦然。在 Scala 中 Tuple
是大小写 class。但是有标准的方法
(1 :: "a" :: true :: HNil).tupled // (1,a,true)
import shapeless.ops.hlist.Tupler
def toTuple[L <: HList](l : L)(implicit tupler: Tupler[L]): tupler.Out = l.tupled
当你不能用你创建类型的方法表达某些东西时 class(我不知道你的实际类型而不是 Nothing
)
case class R[A](a: A)
trait Reduce[L <: HList, Acc <: HList] {
def apply(l: L, acc: Acc): Nothing
}
object Reduce {
implicit def singletonCase[A, Acc <: HList](implicit
tupler: Tupler[Option[(R[A], A)] :: Acc]): Reduce[Option[(R[A], A)] :: HNil, Acc] =
(l, acc) => l match {
case h :: HNil => performFinalStep(toTuple(h :: acc))
}
implicit def notSingletonCase[H, T <: HList, Acc <: HList](implicit
reduce: Reduce[T, H :: Acc]): Reduce[H :: T, Acc] =
(l, acc) => l match {
case h :: t => reduce(t, h :: acc)
}
}
def reduce[L <: HList, Acc <: HList](l: L, acc: Acc)(implicit
r: Reduce[L, Acc]): Nothing = r(l, acc)
下一个麻烦是
Error:(39, 27) overloaded method value performFinalStep with alternatives:
[A1, A2](t: (A1, A2))Nothing <and>
[A1](t: (A1,))Nothing
cannot be applied to (tupler.Out)
case h :: HNil => performFinalStep(toTuple(h :: acc))
你可以多试一种class
trait PerformFinalStep[P <: Product] {
def apply(t: P): Nothing
}
object PerformFinalStep {
implicit def tuple1[A1]: PerformFinalStep[Tuple1[A1]] = t => ???
implicit def tuple2[A1, A2]: PerformFinalStep[Tuple2[A1, A2]] = t => ???
// ...
}
def performFinalStep[T <: Product](t: T)(implicit
pfs: PerformFinalStep[T]) = pfs(t)
trait Reduce[L <: HList, Acc <: HList] {
def apply(l: L, acc: Acc): Nothing
}
object Reduce {
implicit def singletonCase[A, Acc <: HList, P <: Product](implicit
tupler: Tupler.Aux[Option[(R[A], A)] :: Acc, P],
pfs: PerformFinalStep[P]): Reduce[Option[(R[A], A)] :: HNil, Acc] =
(l, acc) => l match {
case h :: HNil => performFinalStep(toTuple(h :: acc))
}
implicit def notSingletonCase[H, T <: HList, Acc <: HList](implicit
reduce: Reduce[T, H :: Acc]): Reduce[H :: T, Acc] =
(l, acc) => l match {
case h :: t => reduce(t, h :: acc)
}
}
def reduce[L <: HList, Acc <: HList](l: L, acc: Acc)(implicit
r: Reduce[L, Acc]): Nothing = r(l, acc)
现在 reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil)
生成 "could not find implicit value for parameter" 但 implicitly[Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: HNil, HNil]]
编译。如果我们明确地替换
reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil)(
implicitly[Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: HNil, HNil]]
)
我们会有
Error:(52, 82) type mismatch;
found : Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: shapeless.HNil,shapeless.HNil]
required: Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: shapeless.HNil,shapeless.HNil.type]
Note: shapeless.HNil >: shapeless.HNil.type, but trait Reduce is invariant in type Acc.
You may wish to define Acc as -Acc instead. (SLS 4.5)
reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil)(implicitly[Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: HNil, HNil]])
所以你应该这样称呼它
reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil : HNil)
我是 shapeless 的新手,尝试解决以下问题。我有不同长度的元组,其中 Option[(R[A], A)] 作为元素,我想过滤元组,以便它只产生一些。请注意,我在编译时没有 Some 或 None,只有 Option。 我想我有一种递归问题,但无法描述它。我有类似以下的想法(我已经将元组转换为 HList:
def performFinalStep[A1](t: Tuple1[A1]) = ???
def performFinalStep[A1, A2](t: Tuple2[A1, A2]) = ???
...
def reduce[T <: HList, A <: HList](l: Option[(R[A], A)] :: T, acc: A) = {
case h :: HNil => performFinalStep(toTuple(h :: acc))
case h :: t => reduce(t, h :: acc) //does not work as it is not known if T's head is Option[(R[A], A)]
}
reduce((Option(R(1), 2), Option(R("S", "s"))).productElements, HNil)
有两件事我不知道,如何将 HList 变回元组以及如何克服 T 的输入?
在 Shapeless 中,可以通过 shapeless.Generic
将 classes 转换为 HList,反之亦然。在 Scala 中 Tuple
是大小写 class。但是有标准的方法
(1 :: "a" :: true :: HNil).tupled // (1,a,true)
import shapeless.ops.hlist.Tupler
def toTuple[L <: HList](l : L)(implicit tupler: Tupler[L]): tupler.Out = l.tupled
当你不能用你创建类型的方法表达某些东西时 class(我不知道你的实际类型而不是 Nothing
)
case class R[A](a: A)
trait Reduce[L <: HList, Acc <: HList] {
def apply(l: L, acc: Acc): Nothing
}
object Reduce {
implicit def singletonCase[A, Acc <: HList](implicit
tupler: Tupler[Option[(R[A], A)] :: Acc]): Reduce[Option[(R[A], A)] :: HNil, Acc] =
(l, acc) => l match {
case h :: HNil => performFinalStep(toTuple(h :: acc))
}
implicit def notSingletonCase[H, T <: HList, Acc <: HList](implicit
reduce: Reduce[T, H :: Acc]): Reduce[H :: T, Acc] =
(l, acc) => l match {
case h :: t => reduce(t, h :: acc)
}
}
def reduce[L <: HList, Acc <: HList](l: L, acc: Acc)(implicit
r: Reduce[L, Acc]): Nothing = r(l, acc)
下一个麻烦是
Error:(39, 27) overloaded method value performFinalStep with alternatives:
[A1, A2](t: (A1, A2))Nothing <and>
[A1](t: (A1,))Nothing
cannot be applied to (tupler.Out)
case h :: HNil => performFinalStep(toTuple(h :: acc))
你可以多试一种class
trait PerformFinalStep[P <: Product] {
def apply(t: P): Nothing
}
object PerformFinalStep {
implicit def tuple1[A1]: PerformFinalStep[Tuple1[A1]] = t => ???
implicit def tuple2[A1, A2]: PerformFinalStep[Tuple2[A1, A2]] = t => ???
// ...
}
def performFinalStep[T <: Product](t: T)(implicit
pfs: PerformFinalStep[T]) = pfs(t)
trait Reduce[L <: HList, Acc <: HList] {
def apply(l: L, acc: Acc): Nothing
}
object Reduce {
implicit def singletonCase[A, Acc <: HList, P <: Product](implicit
tupler: Tupler.Aux[Option[(R[A], A)] :: Acc, P],
pfs: PerformFinalStep[P]): Reduce[Option[(R[A], A)] :: HNil, Acc] =
(l, acc) => l match {
case h :: HNil => performFinalStep(toTuple(h :: acc))
}
implicit def notSingletonCase[H, T <: HList, Acc <: HList](implicit
reduce: Reduce[T, H :: Acc]): Reduce[H :: T, Acc] =
(l, acc) => l match {
case h :: t => reduce(t, h :: acc)
}
}
def reduce[L <: HList, Acc <: HList](l: L, acc: Acc)(implicit
r: Reduce[L, Acc]): Nothing = r(l, acc)
现在 reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil)
生成 "could not find implicit value for parameter" 但 implicitly[Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: HNil, HNil]]
编译。如果我们明确地替换
reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil)(
implicitly[Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: HNil, HNil]]
)
我们会有
Error:(52, 82) type mismatch;
found : Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: shapeless.HNil,shapeless.HNil]
required: Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: shapeless.HNil,shapeless.HNil.type]
Note: shapeless.HNil >: shapeless.HNil.type, but trait Reduce is invariant in type Acc.
You may wish to define Acc as -Acc instead. (SLS 4.5)
reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil)(implicitly[Reduce[Option[(R[Int], Int)] :: Option[(R[String], String)] :: HNil, HNil]])
所以你应该这样称呼它
reduce((Option(R(1), 2), Option(R("S"), "s")).productElements, HNil : HNil)