以下是一个玩具示例,以展示现实生活遗留方法的形状怪异和问题的要点.
正如您所看到的anotherFunc,在将personListexpands类型映射到\/[Throwable,List[\/[Throwable,String]]]不是返回类型但是maping的效果之后personList.再次下面的内容anotherFunc是为了演示目的(实际上有更多有意义的事情发生而不是Option("fakeString")或任何一个.
要求是map personList,如果它right然后对List[Person]返回的每个元素right(从析取返回的一侧)做一些事情.
如何简化/展平返回类型anotherFunc(返回\/[Throwable,List[String]]).可能正在使用其他组合器?
case class Person(name :String)
def personList : \/[Throwable,List[Person]] ={
\/.fromTryCatch{
List(Person("John"))
}
}
def anotherFunc : \/[Throwable,List[\/[Throwable,String]]]= {
personList.map{ pl =>
pl.map{p =>
for{
s <- Option("fakeString").\/>(new Throwable("not found"))
} yield s
}
}
}
Run Code Online (Sandbox Code Playgroud)
诺亚的回答基本上是正确的,但是你应该总是使用traverse而不是a map后跟一个sequence- 两个是等价的,但前者更清晰,效率更高:
def anotherFunc: Throwable \/ List[String] = personList.flatMap { pl =>
pl.traverseU { p =>
for {
// I assume you're doing something more interesting here...
s <- Option("fakeString").\/>(new Throwable("not found"))
} yield s
}
}
Run Code Online (Sandbox Code Playgroud)
不过,我这是一个答案,而不是评论,因为还有另一种方法可以解决这种在某些情况下更优雅的问题.如果您正在使用ListT析取列表进行大量工作,则可以使用monad转换器使其看起来像是在处理单个级别:
type OrThrowable[A] = Throwable \/ A
def personList = ListT[OrThrowable, Person](
\/.fromTryCatch { List(Person("John")) }
)
def anotherFunc: ListT[OrThrowable, String] = personList.flatMap { p =>
Option("fakeString").\/>(new Throwable("not found")).liftM[ListT]
}
Run Code Online (Sandbox Code Playgroud)
现在只需使用anotherFunc.run最终得到一个Throwable \/ List[Person],这完全等同于您当前的代码(但更简洁).
如果你flatMap的personList,然后sequenceU向内部列表可以基本flatten的返回类型:
def anotherFunc: \/[Throwable, List[String]] = {
personList.flatMap(
pl =>
pl.map(
p =>
for {
s <- Option("fakeString").\/>(new Throwable("not found"))
} yield s
).sequenceU
)
}
Run Code Online (Sandbox Code Playgroud)
Intellij用一些红线抱怨这个但是它正确地为我编译并打印出来\/-(List(fakeString)).
在我看来,这个版本看起来更漂亮一些:
def anotherFunc2: \/[Throwable, List[String]] = {
for {
pl <- personList
res <- pl.map(p => Option("fakeString").\/>(new Throwable("not found"))).sequenceU
} yield res
}
Run Code Online (Sandbox Code Playgroud)