Кошки подтверждены с mapN - PullRequest
       6

Кошки подтверждены с mapN

0 голосов
/ 11 февраля 2019

Я новичок с кошками.У меня ошибка с проверенными кошками.Я использую накопитель списка следующим образом:

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 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)
 }
}

У меня есть эта ошибка

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

Можете ли вы помочь мне решить эту ошибку?

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 11 февраля 2019

Много лет назад я написал длинный блог о основной проблеме, с которой вы здесь сталкиваетесь, если вам интересна история или какие-то старые обходные пути, но, к счастью, теперь решение стало намного проще(при условии, что вы используете Scala 2.11 или 2.12): просто добавьте -Ypartial-unification в опции компилятора Scala.Например, если вы используете sbt, это может выглядеть так:

scalacOptions += "-Ypartial-unification"

И все готово.

Если по какой-то причине вы не можете добавить опцию компилятора,Вы должны будете предоставить некоторые параметры типа явно.Вот краткая упрощенная версия:

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):

<console>:22: error: Cannot prove that cats.data.Validated[List[String],Boolean] <:< G[A].
           (dup, values.map(_.check).sequence).mapN((_, _) => 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[ValidationResult, Boolean]).mapN((_, _) => true)
}

Я думаю, вы также можете просто переместить псевдоним типа на уровень пакета, но я не уверен на 100% в этом и не заинтересован в проверке, извините.

Одна сноска: в любое время, когда у вас есть map, а затем sequence, вы можете немного ускорить процесс, используя вместо этого traverse:

  def check: ValidationResult[Boolean] =
    (dup, values.traverse[ValidationResult, Boolean](_.check)).mapN((_, _) => true)

Снова вы можете сбросить параметры типа ипозвольте выводу типа выяснить их, если у вас включен -Ypartial-unification.

...