简体   繁体   English

折叠在NonEmptyList上

[英]Fold on NonEmptyList

I'm trying out cats library but I have hard time navigating between things I should import and create. 我正在尝试使用猫库,但我很难在导入和创建的东西之间导航。 My problem is as follows: 我的问题如下:

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

This is my data structures I want to work with. 这是我想要使用的数据结构。 Every violation should be held as object with msg, checks passed can be aggregated to hold only ids. 每个违规都应该作为具有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))

The last fold leads to an compilation error. 最后一次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 should a perfer candidate for folding. NonEmptyList应该是折叠的候选者。 Validated combine should also be there. 验证组合也应该在那里。 As for my classes, ChechViolation is in NonEmptyList so it does not need a monoid instance. 至于我的类, ChechViolationNonEmptyList因此它不需要monoid实例。 For the ChecksPassed I've created a monoid instance so I don't really get what is missing here. 对于ChecksPassed我创建了一个monoid实例,所以我真的没有得到这里缺少的东西。

EDIT 编辑

I did not include my imports and they are important here: 我没有包含我的进口,它们在这里很重要:

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._

Ok, I figured it out. 好的,我明白了。

So I leave an answer maybe some one will find it helpful. 所以我留下一个答案,也许有人会发现它有用。

There is no possibility to have a Monoid for NonEmptyList. NonEmptyList不可能有Monoid。 Why? 为什么? Monoid needs a neutral element, and for list that would be empty, but our list does not allow this. Monoid需要一个中性元素,对于列表来说是空的,但是我们的列表不允许这样做。

So I've changed how checks are grouped from NEL to List. 所以我改变了将检查从NEL分组到List的方式。

It turned out that I also need to create a Monoid for Validation and it looked like this: 事实证明,我还需要创建一个Monoid for Validation,它看起来像这样:

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

The types if you listen to them carefully guide you well ;) 如果你仔细聆听他们的类型,请指导你;)

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

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