简体   繁体   English

Scala:如何将ValidatedNel的HList转换为HList的ValidatedNel

[英]Scala: How to transform an HList of ValidatedNel into a ValidatedNel of HList

I've been using cats.data.Validated successfully to solve the problem below, but have come into a problem using my existing solution for a case class with more than 22 members (because the constructor cannot be made into a Function ). 我一直在成功使用cats.data.Validated解决以下问题,但是使用我现有的解决方案解决了一个包含22个以上成员的case类的问题(因为无法将构造方法构造为Function )。

Here is my goal: generate a bunch of ValidatedNel[E, T] , sequence them into a ValidatedNel[E, (T1, T2, ...)] , then mapN(DAOClass) (where DAOClass is a case class with the specified arguments). 这是我的目标:生成一堆ValidatedNel[E, T] ,将它们排序为ValidatedNel[E, (T1, T2, ...)] ,然后是mapN(DAOClass) (其中DAOClass是具有指定条件的case class参数)。 This works for fewer than 22 arguments, but fails with more because of two problems: 此方法适用于少于22个参数,但由于两个问题而失败了,但失败了:

  1. (T1, T2, ...) cannot have more than 22 components (T1, T2, ...)不能有超过22个组件
  2. DAOClass.apply cannot be transformed into a Function DAOClass.apply无法转换为Function

So I am looking into using shapeless.HList to handle part 1 and having problems. 因此,我正在研究使用shapeless.HList处理第1部分并遇到问题。 I should be able to use Generic[DAOClass] to satisfactorily handle part 2 when I get to it, or if that doesn't work, use extensible records with a bit more boilerplate. 我应该能够使用Generic[DAOClass]满意地处理第2部分,否则,如果不起作用,请使用可扩展的记录 ,并增加一些样板。

Here is some small example code (not with 22 components): 这是一些小的示例代码(不包含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)

  }

}

This uses the kittens library to sequence the HList . 这使用kittens库对HList

Unfortunately, this gives me a compile error: 不幸的是,这给了我一个编译错误:

[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]                                                                             ^

I have extracted this into a test project; 我已经将其提取到一个测试项目中; here's my build.sbt : 这是我的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"
    )
  )

What am I missing? 我想念什么? Do I need to import more implicits somewhere? 我是否需要在某个地方导入更多隐式内容? Is there a better way to do this? 有一个更好的方法吗?

You forgot to add 你忘了加

scalacOptions += "-Ypartial-unification"

to build.sbt . 建立build.sbt For normal work with cats this is usually mandatory. 对于cats正常工作,这通常是强制性的。

Now 现在

hlistSequence.map(Generic[DAOClass].from)

produces a ValidatedNel[String, DAOClass] : 产生一个ValidatedNel[String, DAOClass]

println(DAOClass.generate) // Valid(DAOClass(1,2))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM