[英]scalaz, Disjunction.sequence returning a list of lefts
在 scalaz 7.2.6 中,我想在Disjunction
上實現sequence
,這樣如果有一個或多個左邊,它返回一個列表,而不是只取第一個(如在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)
? 以及如何改進這段代碼?
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
:
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)
}
}
第一個只是收集結果,最后決定如何處理這些結果,第二個基本相同,只是遞歸函數更簡單,我在這里沒有考慮性能,我使用了:+
,如果您關心使用前置或其他一些集合。
您可能還想查看Validation
和ValidationNEL
,它們與Disjunction
累積失敗不同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.