应用函子
你正在寻求一个future的应用函子。看一下scalaz的应用构造器模式。通过使用zip
,自己编写这个应该相当简单。
(f0 |@| f1 |@| f2)(g) //g is function (Class1, Class2, Class3) => Z
这等同于直接应用:
(f0 <***> (f1, f2))(g)
Scalaz提供了一个名为banana braces的方法,该方法从目标和参数(即你所请求的内容)中形成一个元组。因此,您的解决方案将是:
f0 <|**|> (f1, f2) //that. is. all.
通过为以下类型类定义一个类型类实例,您可以轻松获得所有这些内容:
trait Apply[Z[_]] {
def apply[A, B](f: Z[A => B], a: Z[A]): Z[B]
}
所以,对于未来来说,这看起来像是:
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) }
}
}
实际上,您还需要Pure
和Functor
。在那个地方实现Bind
也是可以的 - 请参见附录。
这个模式的好处是你会开始在各个地方看到它(例如,在Option
、Validation
、List
等中)。例如,2个流的笛卡尔积是:
s1 <|*|> s2
注释
以上所有内容都是基于 scalaz 6,毫无疑问,scalaz 7 针对 2.10 版本将默认提供这些 typeclasses。在 scalaz7 中,Pure
已被重命名为 Pointed
。
附录
未来可能会有其他的 type class 实例:
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
}
(A, B, ...) => Z
的函数f
,并且你想将它提升为一个类型为(F[A], F[B], ...) => F[Z]
的函数时,你需要使用 applicative。在你的情况下,f = (_, _, _)
,而F = Future
。 - missingfaktor