scalaz, Disjunction.sequence returning a list of lefts

◇◆丶佛笑我妖孽 提交于 2019-12-11 06:05:06

问题


In scalaz 7.2.6, I want to implement sequence on Disjunction, such that if there is one or more lefts, it returns a list of those, instead of taking only the first one (as in Disjunction.sequenceU):

import scalaz._, Scalaz._

List(1.right, 2.right, 3.right).sequence
res1: \/-(List(1, 2, 3))

List(1.right, "error2".left, "error3".left).sequence
res2: -\/(List(error2, error3))

I've implemented it as follows and it works, but it looks ugly. Is there a getRight method (such as in scala Either class, Right[String, Int](3).right.get)? And how to improve this code?

implicit class RichSequence[L, R](val l: List[\/[L, R]]) {
  def getLeft(v: \/[L, R]):L = v match { case -\/(x) => x }
  def getRight(v: \/[L, R]):R = v match { case \/-(x) => x }

  def sequence: \/[List[L], List[R]] =
    if (l.forall(_.isRight)) {
      l.map(e => getRight(e)).right
    } else {
      l.filter(_.isLeft).map(e => getLeft(e)).left
    }
}

回答1:


Playing around I've implemented a recursive function for that, but the best option would be to use separate:

implicit class RichSequence[L, R](val l: List[\/[L, R]]) {
  def sequence: \/[List[L], List[R]] = {
    def seqLoop(left: List[L], right: List[R], list: List[\/[L, R]]): \/[List[L], List[R]] =
      list match {
        case (h :: t) =>
          h match {
            case -\/(e) => seqLoop(left :+ e, right, t)
            case \/-(s) => seqLoop(left, right :+ s, t)
          }
        case Nil =>
          if(left.isEmpty) \/-(right)
          else -\/(left)
    }
    seqLoop(List(), List(), l)
  }


  def sequenceSeparate: \/[List[L], List[R]] = {
    val (left, right) = l.separate[\/[L, R], L, R]
    if(left.isEmpty) \/-(right)
    else -\/(left)
  }
}

The first one just collects results and at the end decide what to do with those, the second its basically the same with the exception that the recursive function is much simpler, I didn't think about performance here, I've used :+, if you care use prepend or some other collection.

You may also want to take a look at Validation and ValidationNEL which unlike Disjunction accumulate failures.



来源:https://stackoverflow.com/questions/39471935/scalaz-disjunction-sequence-returning-a-list-of-lefts

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!