Scala 如何展平析取类型
如果我有以下方法Scala 如何展平析取类型,scala,scalaz,Scala,Scalaz,如果我有以下方法 def getMyList :\/[Throwable,List[\/[Throwable,Int]]] ={ .... } 如何将getMyList的类型展平到\/[Throwable,List[Int]]如果通过展平,您的意思是从列表[\/[Throwable,Int]]]中删除左侧类型,那么您可以映射外部析取,并收集右侧类型: list.map(_.collect{ case \/-(x) => x}) 我不认为对/存在更高阶的“扁平化”。看起来Valid
def getMyList :\/[Throwable,List[\/[Throwable,Int]]] ={
....
}
如何将
getMyList
的类型展平到\/[Throwable,List[Int]]
如果通过展平,您的意思是从列表[\/[Throwable,Int]]]
中删除左侧类型,那么您可以映射外部析取,并收集右侧类型:
list.map(_.collect{ case \/-(x) => x})
我不认为对/存在更高阶的“扁平化”。看起来Validateion和ValidationNEL将是解决此问题的更好选择。然而,这里是/的“脏”解决方案,它将首先返回fail。若你们想积累失败,验证是一条路要走
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)
我们使用以下方法,其中.ssaccess创建一个\/[\uu,Seq[T]]
,.sFail创建一个\/[Throwable,\u]
,并将所有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
s只需flatMap
和sequenceU
,它都在scalaz中:
def flatten(e: \/[Throwable,List[\/[Throwable,Int]]]): \/[Throwable,List[Int]] = {
e.flatMap(a => a.sequenceU)
}
回答得好,你能简单解释一下sequenceU
。我尝试使用普通的序列
,但失败。@bmaderbachersequenceU
自动为应用程序
实例推断正确的类型构造函数。这里有一篇关于这个主题的文章值得一读:@GabrielePetronella说了什么:)@GabrielePetronella谢谢你的解释。来自Haskell Scala的类型推断,有时真的很烦人。您可能还想看看traverseU作为sequenceU的潜在替代品,以便在前面获得\/[Throwable,List[Int]]
。请参阅BindSyntax
-中的连接。这提供了join
,对于具有Bind[A]
的所有类型A
,它本质上是flatten
的同义词。