以下是代码:
import org.scalactic._
import Accumulation._
def f(x: Int): List[Double] Or Every[String] =
if (x > 0) Good(List(x, x * 2, x * 3))
else Bad(Many("One", "Two", "Three"))
def g(y: Double): List[Char] Or Every[String] =
if (y > 5.0) Good(List('a', 'b', 'c'))
else Bad(Many("Four", "Five", "Six"))
// Now I need a composition g(f(...)):
// def h(x: Int): List[Char] Or Every[String] = ???
// Straightforward solution
def h(x: Int) =
f(x).transform(_.map(g).combined, Bad(_)).
flatMap(item => Good(item.flatMap(identity)))
// h(-1)
// = Bad(Many(One, Two, Three))
// h(2)
// = Bad(Many(Four, Five, Six, Four, Five, Six))
// h(42)
// = Good(List(a, b, c, a, b, c, a, b, c))
函数体被虚拟占位符替换,特定于域的类型被替换为中性,但我相信签名很简单。
如何撰写这些功能?有内置的方法吗?我想避免flatMap / transform mess。
谢谢。
答案 0 :(得分:2)
我发现在for
理解中更容易阅读。由于Ors
偏向Good
方面,您至少可以摆脱transform
乏味的一点:
def h(x: Int): List[Char] Or Every[String] = {
for {
y <- f(x)
z <- y.map(g).combined
} yield {
z.flatten
}
}