David Portabella - 2 months ago 36

Scala Question

In scalaz 7.2.6, I want to implement

`sequence`

`Disjunction`

`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`

`Either`

`Right[String, Int](3).right.get)`

`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

}

}

Answer

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.

Source (Stackoverflow)

Comments