首页 > 解决方案 > Scala:如何将 ValidatedNel 的 HList 转换为 HList 的 ValidatedNel

问题描述

我一直在cats.data.Validated成功地使用来解决下面的问题,但是在使用我现有的解决方案时遇到了一个问题,该解决方案用于具有超过 22 个成员的案例类(因为无法将构造函数制作为 a Function)。

这是我的目标:生成一堆ValidatedNel[E, T],将它们排序为 a ValidatedNel[E, (T1, T2, ...)],然后mapN(DAOClass)(其中DAOClassacase class具有指定的参数)。这适用于少于 22 个参数,但由于两个问题而失败更多:

  1. (T1, T2, ...)不能超过 22 个组件
  2. DAOClass.apply不能转化为Function

所以我正在研究使用shapeless.HList来处理第 1 部分并遇到问题。当我到达第 2 部分时,我应该能够Generic[DAOClass]满意地处理它,或者如果这不起作用,请使用 带有更多样板的可扩展记录。

这是一些小示例代码(不是 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"
    )
  )

我错过了什么?我需要在某处导入更多的隐式吗?有一个更好的方法吗?

标签: scalashapelessscala-cats

解决方案


你忘了添加

scalacOptions += "-Ypartial-unification"

build.sbt. 对于正常工作,cats这通常是强制性的。

现在

hlistSequence.map(Generic[DAOClass].from)

产生一个ValidatedNel[String, DAOClass]

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

推荐阅读