首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用mapN验证的Cats

使用mapN验证的Cats
EN

Stack Overflow用户
提问于 2019-02-12 01:18:49
回答 1查看 926关注 0票数 6

我是Cats的初学者。我对经过验证的猫有一个错误。我使用这样的列表累加器:

代码语言:javascript
复制
case class Type(
 name: String,
 pattern: String,
 primitiveType: PrimitiveType = PrimitiveType.string,
 sample: Option[String] = None,
 comment: Option[String] = None,
 stat: Option[Stat] = None
) {
 type ValidationResult[A] = Validated[List[String], A]

 def checkValidity(): ValidationResult[Boolean] = {
  val errorList: mutable.MutableList[String] = mutable.MutableList.empty

  val patternIsValid = Try {
   primitiveType match {
    case PrimitiveType.struct =>
    case PrimitiveType.date =>
      new SimpleDateFormat(pattern)
    case PrimitiveType.timestamp =>
      pattern match {
        case "epoch_second" | "epoch_milli" =>
        case _ if PrimitiveType.formatters.keys.toList.contains(pattern) =>
        case _ =>
          DateTimeFormatter.ofPattern(pattern)
      }
    case _ =>
      Pattern.compile(pattern)
   }
 }
 if (patternIsValid.isFailure)
  errorList += s"Invalid Pattern $pattern in type $name"
 val ok = sample.forall(this.matches)
 if (!ok)
  errorList += s"Sample $sample does not match pattern $pattern in type $name"
 if (errorList.nonEmpty)
  Invalid(errorList.toList)
 else
  Valid(true)
}
}

当我在case类类型中使用此函数时:

代码语言:javascript
复制
case class Types(types: List[Type]) {

 type ValidationResult[A] = Validated[List[String], A]

 def checkValidity(): ValidationResult[Boolean] = {
   val typeNames = types.map(_.name)
   val dup: ValidationResult[Boolean] =
   duplicates(typeNames, s"%s is defined %d times. A type can only be defined once.")
  (dup,types.map(_.checkValidity()).sequence).mapN((_,_) => true)
 }
}

我有这个错误

代码语言:javascript
复制
Error:(29, 39) Cannot prove that cats.data.Validated[List[String],Boolean] <:< G[A].
(dup,types.map(_.checkValidity()).sequence: _*).mapN((_,_) => true)

你能帮我解决这个错误吗?

谢谢你的帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-12 03:49:03

多年前,如果你对历史或一些旧的变通方法感兴趣,我写了一篇关于你在这里遇到的潜在问题的long blog post,但幸运的是,现在解决方案更容易了(假设你使用的是Scala 2.11或2.12):只需将-Ypartial-unification添加到你的Scala编译器选项中。例如,如果您使用的是sbt,则可能如下所示:

代码语言:javascript
复制
scalacOptions += "-Ypartial-unification"

你就完事了。

如果由于某些原因不能添加编译器选项,则必须显式提供一些类型参数。这是一个快速的简化版本:

代码语言:javascript
复制
import cats.data.Validated, cats.implicits._


case class Foo(i: Int) {
  type ValidationResult[A] = Validated[List[String], A]

  def check: ValidationResult[Boolean] =
    if (i < 0) Validated.invalid(List("bad")) else Validated.valid(true)
}

case class Foos(values: List[Foo]) {
  type ValidationResult[A] = Validated[List[String], A]

  def dup: ValidationResult[Unit] = Validated.valid(())
  def check: ValidationResult[Boolean] =
    (dup, values.map(_.check).sequence).mapN((_, _) => true)
}

这将失败,并显示您看到的错误(假设您尚未添加-Ypartial-unification):

代码语言:javascript
复制
<console>:22: error: Cannot prove that cats.data.Validated[List[String],Boolean] <:< G[A].
           (dup, values.map(_.check).sequence).mapN((_, _) => true)
                                     ^

要修复它,您可以编写以下代码:

代码语言:javascript
复制
case class Foos(values: List[Foo]) {
  type ValidationResult[A] = Validated[List[String], A]

  def dup: ValidationResult[Unit] = Validated.valid(())
  def check: ValidationResult[Boolean] =
    (dup, values.map(_.check).sequence[ValidationResult, Boolean]).mapN((_, _) => true)
}

我想你也可以把类型别名移到包级别,但我不是百分之百确定,也没有动力去检查,抱歉。

一个脚注:任何时候你使用map,然后使用sequence,你都可以通过使用traverse让事情变得更快:

代码语言:javascript
复制
  def check: ValidationResult[Boolean] =
    (dup, values.traverse[ValidationResult, Boolean](_.check)).mapN((_, _) => true)

同样,如果启用了-Ypartial-unification,您可以删除类型参数,并让类型推断找出它们。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54635826

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档