2014-09-22 134 views

回答

9

只是flatMapsequenceU,这一切都在scalaz:

def flatten(e: \/[Throwable,List[\/[Throwable,Int]]]): \/[Throwable,List[Int]] = { 
    e.flatMap(a => a.sequenceU) 
    } 
+0

很好的答案,你可以简单解释一下'sequenceU'。我用普通的“序列”尝试,但失败了。 – bmaderbacher 2014-09-23 00:21:42

+2

@bmaderbacher'sequenceU'自动推断'Applicative'实例的正确类型构造函数。这里有一篇值得阅读的文章:http://eed3si9n.com/learning-scalaz-day15 – 2014-09-23 00:23:32

+0

什么@GabrielePetronella说:) – Noah 2014-09-23 00:27:26

1

如果扁平化,您的意思是List[\/[Throwable,Int]]拆下左类型,那么你就可以map外部析取和collect正确的类型:

list.map(_.collect{ case \/-(x) => x}) 
0

我不认为一些更高的顺序“扁平”存在于/。看起来像Validateion & ValidationNEL将是更好的选择这个问题。然而,这是/的“脏”解决方案,它将首先失败。如果你希望积累的失败验证是路要走

val getMyList: \/[Throwable,List[\/[Throwable,Int]]] = 
    //\/-(List(-\/(new RuntimeException("test")), \/-(1))) 
    \/-(List(\/-(2), \/-(1))) 


    val flatten = getMyList.fold(\/.left, _.foldLeft(\/.right[Throwable, List[Int]](List.empty[Int])) { 
    case (\/-(list), \/-(i)) => \/-(list :+ i) 
    case (\/-(list), -\/(err)) => -\/(err) 
    case (-\/(err), _) => -\/(err) 
    }) 

    println(flatten) 
+0

请参阅'BindSyntax'中的'join' - https://github.com/scalaz/scalaz/blob/series/7.1.x/core/src/main/scala/scalaz/syntax/BindSyntax.scala# L15。这提供了'join',它与具有'Bind [A]'的所有类型'A'的'flatten'基本同义。 – drstevens 2014-09-23 14:49:58

0

我们用下面的方法,其中.sSuccess创建一个\/[_, Seq[T]]和.sFail创建包含所有可抛出错误消息级联一个\/[Throwable, _]

implicit class CondenseEither[T](seq: Seq[\/[Throwable,T]]) = { 
    def condenseSeq: \/[Throwable, Seq[T]] = { 
    val errs = seq.filter(_.isLeft).map(_.toEither) 
    if(errs.isEmpty) seq.map(_.toEither).map(_.right.get).sSuccess 
    else errs.map(_.left.get.getMessage).mkString(", ")).sFail 
    } 
} 

有可能是一个办法做到这一点没有toEither小号