scalaz, Disjunction.sequence 返回左列表 [英] scalaz, Disjunction.sequence returning a list of lefts
问题描述
在 scalaz 7.2.6 中,我想在 Disjunction
上实现 sequence
,这样如果有一个或多个左边,它返回一个列表,而不是只取第一个(如 Disjunction.sequenceU
):
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))
我已按如下方式实现它并且它有效,但它看起来很难看.是否有 getRight
方法(例如在 scala Either
类中,Right[String, Int](3).right.get)
?以及如何改进这段代码?
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
}
}
推荐答案
我已经为此实现了一个递归函数,但最好的选择是使用 separate
:
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.
您可能还想看看 Validation
和 ValidationNEL
,它们不同于 Disjunction
累积失败.
You may also want to take a look at Validation
and ValidationNEL
which unlike Disjunction
accumulate failures.
这篇关于scalaz, Disjunction.sequence 返回左列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!