7

而不是xs map f map g更有效地编写xs map { x => g(f(x)) },并且类似地用于多个filter操作。

如果我flatMap连续有两个或多个 s,有没有办法将它们组合成一个,这可能更有效?例如

def f(x: String) = Set(x, x.reverse)
def g(x: String) = Set(x, x.toUpperCase)

Set("hi", "bye") flatMap f flatMap g  
  // Set(bye, eyb, IH, BYE, EYB, ih, hi, HI)
4

3 回答 3

11
于 2012-09-02T10:20:23.450 回答
5

In scalaz there is a way to compose functions like a -> m b and b -> m c into a -> m c (like the function here, from String to Set[String]). They are called Kleisli functions, by the way. In haskell this is done simply with >=> on those functions. In scala you'll have to be a bit more verbose (by the way, I've changed the example a bit: I couldn't make it work with Set, so I've used List):

scala> import scalaz._, std.list._
import scalaz._
import std.list._

scala> def f(x: String) = List(x, x.reverse)
f: (x: String)List[String]

scala> def g(x: String) = List(x, x.toUpperCase)
g: (x: String)List[java.lang.String]

scala> val composition = Kleisli(f) >=> Kleisli(g)
composition: scalaz.Kleisli[List,String,java.lang.String] = scalaz.KleisliFunctions$$anon$18@37911406

scala> List("hi", "bye") flatMap composition
res17: List[java.lang.String] = List(hi, HI, ih, IH, bye, BYE, eyb, EYB)
于 2012-09-02T20:09:54.257 回答
2

您为过滤器描述的方法基本上跳过了中间集合的创建。

至少在flatMap函数内部创建了内部集合,所以我无法想象有任何方法可以在不更改函数的情况下跳过该创建。

您可以尝试使用视图,尽管我不确定这对 flatMap 是否有用。

或者,您可以multiFlatMap直接从函数结果构建最终集合,而不将从函数返回的中间集合填充到新集合中。

不知道这是否可行。我至少看到一些严重的类型挑战即将到来,因为您需要传入一个函数序列,其中每个函数返回一个集合 A,其中 A 是下一个函数的输入类型。至少在任意类型和任意数量的函数的一般情况下,这听起来有些挑战。

于 2012-09-02T06:53:15.110 回答