Applicative Functors
What you are asking for is an applicative functor for a future. See scalaz Applicative Builder pattern. It should be rather trivial to roll your own on the back of zip
(f0 |@| f1 |@| f2)(g) //g is function (Class1, Class2, Class3) => Z
This is equivalent to the direct applicative:
(f0 <***> (f1, f2))(g)
Scalaz ships with a banana braces method which forms a tuple from the target and the arguments (i.e. what you asked for). So your solution will be:
f0 <|**|> (f1, f2) //that. is. all.
You get all this simply by defining a typeclass instance for the following typeclass:
trait Apply[Z[_]] {
def apply[A, B](f: Z[A => B], a: Z[A]): Z[B]
}
So for future this looks like:
implicit val FutureApply = new Apply[Future] {
def apply[A, B](f: Future[A => B], a: Future[A]): Future[B] =
(f zip a) map { case (fn, a1) => fn(a1) }
}
}
(Actually you'd need Pure and Functor as well. Might as well implement Bind whilst you're at it - see appendix)
The great thing about this pattern is that you will start to see it everywhere (e.g. in Option, in Validation, in List etc). For example, the cartesian product of 2 streams is:
s1 <|*|> s2
Notes
All the above assuming scalaz 6, doubtless scalaz 7 for 2.10 will ship with these typeclasses by default. Pure has been renamed Pointed in scalaz7.
Appendix
Other type class instances for future:
implicit val FuturePure = new Pure[Future] {
def pure[A](a: =>A): Future[A] = Future { a }
}
implicit val FutureBind = new Bind[Future] {
def bind[A, B](a: Future[A], f: A => Future[B]): Future[B] = a flatMap f
}
implicit val FutureFunctor = new Functor[Future] {
def map[A, B](a: Future[A], f: A => B): Future[B] = a map f
}