是否有简短的方法在scala中组合这些函数?

时间:2015-08-26 16:16:15

标签: scala scalactic

以下是代码:

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。

谢谢。

1 个答案:

答案 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
  }
}