以下是一个玩具示例,以演示现实生活中的传统方法的形状怪异度和问题要点。
如您所见anotherFunc
,映射后的personList
扩展类型\/[Throwable,List[\/[Throwable,String]]]
不是预期的返回类型,而是map
ing的作用personList
。再次在下面显示的内容anotherFunc
是出于演示目的(实际上,发生了更多有意义的事情,而不是其中的Option("fakeString")
任何事情。
需求是map
personList
,如果需要,right
则对List[Person]
返回的每个元素right
(从析取函数返回的那一侧)执行某些操作。
如何简化/展平返回的类型anotherFunc
(以return \/[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
}
}
}
诺亚的回答基本上是正确的,但您应始终使用traverse
而不是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
}
}
不过,我将其作为答案而不是评论,因为还有另一种解决这类问题的方法,在某些情况下这种解决方案可能更优雅。如果您要处理大量的析取列表,则可以使用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]
}
现在只需anotherFunc.run
在末尾使用即可得到一个Throwable \/ List[Person]
,它与您当前的代码完全等效(但更加简洁)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句