我正在寻找一种方法将多个JsResult组合成一个。 这是我第一次尝试不使用Shapeless
def combineJsResult[A,B](res1: JsResult[A], res2: JsResult[B]): JsResult[(A, B)] = (res1, res2) match {
case (r1: JsError, r2: JsError) => r1 ++ r2
case (JsSuccess(r1, _), JsSuccess(d, _)) => JsSuccess(r1 -> d)
case (r1: JsError, _) => r1
case (_, r2: JsError) => r2
}
我想要的是一个带有n个JsResult的函数,并将它们组合成一个JsResult [(A,B,C,...)]。现在我知道scala关于抽象的限制了。 我尝试使用Shapeless多个代码,但由于JsResult是一个类型构造函数和方差问题,因此没有编译。 这是我脑海中的算法:
编写一个函数,将任意类型的JsResult的HList作为参数。 foldRight在列表中使用JsSuccess(HNil)作为初始元素,并将上述函数的变体(将结果类型更改为JsResult [HList])作为折叠函数。
这是我的最终代码(不编译)
import play.api.libs.json.{JsError, JsResult, JsSuccess}
import shapeless.{Generic, HList, HNil, Poly2}
object merger extends Poly2 {
def apply = at{ (res1: JsResult[_], res2: JsResult[_]) => {
(res1, res2) match {
case (r1: JsError, r2: JsError) => r1 ++ r2
case (JsSuccess(r1, _), JsSuccess(d, _)) => JsSuccess(r1 :: d :: HNil)
case (r1: JsError, _) => r1
case (_, r2: JsError) => r2
}
} }
}
def combineJsResults[P <: Product, L <: HList](p: P)(implicit gen: Generic.Aux[P, L]) = {
gen.to(p).foldRight[JsResult[HList]](JsSuccess(HNil))(merger)
}
combineJsResults(JsSuccess(1), JsSuccess("2"), JsSuccess(true))
非常感谢您帮助我了解如何解决此问题。
编辑:我取得了一些进展
import play.api.libs.json.{JsError, JsSuccess}
import shapeless._
object combine extends Poly2 {
def concatSuccess[L, R <: HList](l: JsSuccess[L], r: JsSuccess[R]): JsSuccess[L :: R] = JsSuccess(l.value :: r.value)
implicit def successSuccess[L, R <: HList] = at[JsSuccess[L], JsSuccess[R]](concatSuccess)
implicit def errorSuccess[R <: HList] = at[JsError, JsSuccess[R]]((l: JsError, r : JsSuccess[R]) => l)
implicit val errorError = at[JsError, JsError](_ ++ _)
implicit def successError[S] = at[JsSuccess[S], JsError]((l: JsSuccess[S], r: JsError) => r)
}
(JsSuccess(true) :: HNil).foldRight(JsSuccess(HNil))(combine)
(JsError("error") :: HNil).foldRight(JsSuccess(HNil))(combine)
val res1 = (JsSuccess(true) :: JsSuccess(1) :: HNil).foldRight(JsSuccess(HNil))(combine)
(JsError("error1") :: JsError("error2") :: HNil).foldRight(JsSuccess(HNil))(combine)
(JsSuccess(true) :: JsError("error2") :: HNil).foldRight(JsSuccess(HNil))(combine)
此代码编译,它成功地将JsResult [_]列表转换为JsResult [HList],现在我需要能够将该HList转换为元组以将其传递给案例类的tupled方法。 我查看了涉及使用Generic对象的示例,但它没有编译,因为Generic [some case class] .to方法需要一个Repr参数而不是HList。 有没有人有任何想法? 感谢