Scala:如何将 ValidatedNel 的 HList 转换为 HList 的 ValidatedNel
Scala: How to transform an HList of ValidatedNel into a ValidatedNel of HList
我一直在使用 cats.data.Validated
成功地解决了下面的问题,但是在使用我现有的解决方案来处理超过 22 个成员的案例 class 时遇到了问题(因为构造函数不能做成Function
).
我的目标是:生成一堆 ValidatedNel[E, T]
,将它们排列成 ValidatedNel[E, (T1, T2, ...)]
,然后是 mapN(DAOClass)
(其中 DAOClass
是 case class
带有指定的参数)。这适用于少于 22 个参数,但由于两个问题而失败:
(T1, T2, ...)
不能超过 22 个组件
DAOClass.apply
无法转换为 Function
所以我正在考虑使用 shapeless.HList
来处理第 1 部分并遇到问题。我应该可以使用 Generic[DAOClass]
to satisfactorily handle part 2 when I get to it, or if that doesn't work, use extensible records 和更多样板文件。
这是一些小示例代码(不包含 22 个组件):
package example
import cats.syntax.validated._
import cats.data.ValidatedNel
import cats.sequence._
import shapeless._
case class DAOClass(a: Int, b: Int)
object DAOClass {
def generate: ValidatedNel[String, DAOClass] = {
val hlist: ValidatedNel[String, Int] :: ValidatedNel[String, Int] :: HNil =
1.validNel :: 2.validNel :: HNil
val hlistSequence: ValidatedNel[String, Int :: Int :: HNil] = hlist.sequence
hlistSequence.map(Generic[DAOClass].from)
}
}
这使用 kittens
库对 HList
进行排序。
不幸的是,这给了我一个编译错误:
[error] ...src/main/scala/example/DAOClass.scala:17:73: cannot construct sequencer, make sure that every item of your hlist shapeless.:: [cats.data.ValidatedNel[String,Int],shapeless.::[cats.data.ValidatedNel[String,Int],shapeless.HNil]] is an Apply
[error] val hlistSequence: ValidatedNel[String, ::[Int, ::[Int, HNil]]] = hlist.sequence
[error] ^
我已经将其提取到一个测试项目中;这是我的 build.sbt
:
lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "com.example",
scalaVersion := "2.12.6",
version := "0.1.0-SNAPSHOT"
)),
name := "shapeless-validation",
resolvers ++= Seq(
Resolver.sonatypeRepo("releases")
),
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.3.3",
"org.scalatest" %% "scalatest" % "3.0.5" % "test",
"org.typelevel" %% "cats-core" % "1.1.0",
"org.typelevel" %% "kittens" % "1.1.0"
)
)
我错过了什么?我需要在某处导入更多隐式吗?有更好的方法吗?
您忘记添加
scalacOptions += "-Ypartial-unification"
到build.sbt
。对于 cats
的正常工作,这通常是强制性的。
现在
hlistSequence.map(Generic[DAOClass].from)
产生 ValidatedNel[String, DAOClass]
:
println(DAOClass.generate) // Valid(DAOClass(1,2))
我一直在使用 cats.data.Validated
成功地解决了下面的问题,但是在使用我现有的解决方案来处理超过 22 个成员的案例 class 时遇到了问题(因为构造函数不能做成Function
).
我的目标是:生成一堆 ValidatedNel[E, T]
,将它们排列成 ValidatedNel[E, (T1, T2, ...)]
,然后是 mapN(DAOClass)
(其中 DAOClass
是 case class
带有指定的参数)。这适用于少于 22 个参数,但由于两个问题而失败:
(T1, T2, ...)
不能超过 22 个组件DAOClass.apply
无法转换为Function
所以我正在考虑使用 shapeless.HList
来处理第 1 部分并遇到问题。我应该可以使用 Generic[DAOClass]
to satisfactorily handle part 2 when I get to it, or if that doesn't work, use extensible records 和更多样板文件。
这是一些小示例代码(不包含 22 个组件):
package example
import cats.syntax.validated._
import cats.data.ValidatedNel
import cats.sequence._
import shapeless._
case class DAOClass(a: Int, b: Int)
object DAOClass {
def generate: ValidatedNel[String, DAOClass] = {
val hlist: ValidatedNel[String, Int] :: ValidatedNel[String, Int] :: HNil =
1.validNel :: 2.validNel :: HNil
val hlistSequence: ValidatedNel[String, Int :: Int :: HNil] = hlist.sequence
hlistSequence.map(Generic[DAOClass].from)
}
}
这使用 kittens
库对 HList
进行排序。
不幸的是,这给了我一个编译错误:
[error] ...src/main/scala/example/DAOClass.scala:17:73: cannot construct sequencer, make sure that every item of your hlist shapeless.:: [cats.data.ValidatedNel[String,Int],shapeless.::[cats.data.ValidatedNel[String,Int],shapeless.HNil]] is an Apply
[error] val hlistSequence: ValidatedNel[String, ::[Int, ::[Int, HNil]]] = hlist.sequence
[error] ^
我已经将其提取到一个测试项目中;这是我的 build.sbt
:
lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "com.example",
scalaVersion := "2.12.6",
version := "0.1.0-SNAPSHOT"
)),
name := "shapeless-validation",
resolvers ++= Seq(
Resolver.sonatypeRepo("releases")
),
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.3.3",
"org.scalatest" %% "scalatest" % "3.0.5" % "test",
"org.typelevel" %% "cats-core" % "1.1.0",
"org.typelevel" %% "kittens" % "1.1.0"
)
)
我错过了什么?我需要在某处导入更多隐式吗?有更好的方法吗?
您忘记添加
scalacOptions += "-Ypartial-unification"
到build.sbt
。对于 cats
的正常工作,这通常是强制性的。
现在
hlistSequence.map(Generic[DAOClass].from)
产生 ValidatedNel[String, DAOClass]
:
println(DAOClass.generate) // Valid(DAOClass(1,2))