无形过滤选项列表

时间:2018-11-27 09:14:13

标签: scala shapeless

我是无形的新手,并尝试解决以下问题。我将Option [(R [A],A)]作为元素使用了不同长度的元组,并且希望对元组进行某种过滤,使其仅产生Some。请注意,在编译时我没有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的键入?

1 个答案:

答案 0 :(得分:1)

在无形状转换中,可以通过$ npm install -g cordova-check-plugins 将案例类转换为HList,反之亦然。在Scala中,$ cordova-check-plugins --update=auto 是案例类。但是有标准的方法

shapeless.Generic

当您无法使用方法表达某些内容时,可以创建一个类型类(我不知道您的实际类型,而不是Tuple

(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

下一个麻烦是

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)) 产生“找不到参数的隐式值”,但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)

我们将拥有

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]]
)