5

我正在尝试猫库,但我很难在我应该导入和创建的东西之间导航。我的问题如下:

sealed trait Checks
case class CheckViolation(id: Long, msg: String) extends Checks
case class ChecksPassed(ids: Seq[Long]) extends Checks

这是我想要使用的数据结构。每个违规行为都应作为对象与 msg 一起保存,通过的检查可以聚合以仅保存 id。

object BusinessRuleSetValidation extends App {

  type BRValidationResult = Validated[NonEmptyList[CheckViolation], ChecksPassed]

  def run(): BRValidationResult = {

    implicit val monoidChecksPassed = new Monoid[ChecksPassed] {
      override def empty: ChecksPassed = ChecksPassed(Seq())

      override def combine(x: ChecksPassed, y: ChecksPassed): ChecksPassed = ChecksPassed(x.ids ++ y.ids)
    }



    val check1: BRValidationResult = valid(ChecksPassed(2L))
    val check2: BRValidationResult = invalidNel(CheckViolation(1, "This check was violated"))
    val check3: BRValidationResult = invalidNel(CheckViolation(2, "This is a violation"))


    val p = Foldable[NonEmptyList].fold(NonEmptyList(check1, check2, check3))

最后fold导致编译错误。

BusinessRuleSetValidation.scala:48: could not find implicit value for parameter A: cats.Monoid[cats.data.Validated[cats.data.OneAnd[com.adform.br.server.model.validation.CheckViolation,[+A]List[A]],com.adform.br.server.model.validation.ChecksPassed]]
[error]     val p = Foldable[NonEmptyList].fold(NonEmptyList(check1, check2, check3))

NonEmptyList应该是折叠的更好候选人。验证的组合也应该在那里。至于我的类,ChechViolation是 inNonEmptyList所以它不需要一个 monoid 实例。对于ChecksPassed我已经创建了一个幺半群实例,所以我并没有真正得到这里缺少的东西。

编辑

我没有包括我的进口,它们在这里很重要:

import cats._
import cats.data.Validated._
import cats.data.{NonEmptyList, Validated, Xor}
import cats.data.OneAnd.oneAndFoldable
import cats.std.all._
import cats.syntax.apply._
import cats.syntax.order._
import cats.syntax.xor._
import cats.syntax.semigroup._
4

1 回答 1

6

好的,我想通了。

所以我留下一个答案,也许有人会觉得它有帮助。

NonEmptyList 不可能有 Monoid。为什么?Monoid 需要一个中性元素,而对于列表,它会是空的,但我们的列表不允许这样做。

所以我改变了检查从 NEL 到 List 的分组方式。

事实证明,我还需要创建一个用于验证的 Monoid,它看起来像这样:

   implicit val brValidationResutlMonoid = new Monoid[BRValidationResult] {
      override def empty: BRValidationResult = valid(ChecksPassed(Seq.empty))

      override def combine(x: BRValidationResult, y: BRValidationResult): BRValidationResult = (x,y) match {
        case (Valid(a),Valid(b)) => valid(ChecksPassed(a.ids ++ b.ids))
        case (Valid(_), k @ Invalid(_)) => k
        case (f @ Invalid(_), Valid(_)) => f
        case (Invalid(l1),Invalid(l2)) => Invalid(l1.combine(l2))
      }
    }

如果你仔细听他们的类型会很好地指导你;)

于 2015-09-09T12:31:21.780 回答