Scala 在这种情况下如何定义Applicative?

Scala 在这种情况下如何定义Applicative?,scala,concurrency,monads,applicative,Scala,Concurrency,Monads,Applicative,这是我上一篇文章的后续文章。我再次阅读这篇文章是为了理解这里描述的设计 它们引入了一个类似于的作业单子Job[T]是一种数据获取操作,用于获取类型为T的数据(可能包括其他操作,即,它是一个数据获取序列) 它们还引入了一个函数execute,用于实际执行Job[T]操作并返回未来 def execute[T](job: Job[T])(implicit ec: ExecutionContext): Future[T] = { ... } 对于并发数据获取,它们添加了新的PairJob,以及Map

这是我上一篇文章的后续文章。我再次阅读这篇文章是为了理解这里描述的设计

它们引入了一个类似于的
作业
单子
Job[T]
是一种数据获取操作,用于获取类型为
T
的数据(可能包括其他操作,即,它是一个数据获取序列)

它们还引入了一个函数
execute
,用于实际执行
Job[T]
操作并返回未来

def execute[T](job: Job[T])(implicit ec: ExecutionContext): Future[T] = { ... }
对于并发数据获取,它们添加了新的
PairJob
,以及
MapJob

case class MapJob[S, T](f: S => T, job: Job[S]) extends Job[T]
case class PairJob[S, T](jobS: Job[S], jobT: Job[T]) extends Job[(S, T)]
现在他们可以写:

val jobA: FetchJob[A] = ...
val jobB: FetchJob[B] = ...
val f: A => B = ...

// jobAB is a MapJob of "f" and PairJob of jobA and jobB
val jobAB = (jobA |@| jobB) {(a, b) => f(a, b)}

我的问题是如何将
Job[T]
定义为
Applicative
,以编写上述示例中的代码。

很快你就有了PairJob,你就有了Applicative所需的东西

对于任何泛型类型G,(这里是Job)

如果您有配对:

def pair[A,B](ga: G[A], gb: G[B]): G[(A,B)]
(对于Job,它只是
PairJob(ga,gb)

并且还可以映射,这样您就可以轻松地实现应用

def ap[A, B](ga: ⇒ G[A])(f: ⇒ G[A ⇒ B]): G[B] = {
   val argAndFunc : G[(A, A => B)] = pair(ga, f)
   argAndFunc map {case (arg, func) => func(arg)}
}
反之亦然,如果你有ap和map,你很容易得到一对

def pair[A,B](ga: G[A], gb: G[B]): G[(A,B)] = {
  val pairWithB : G[B => (A,B]) = ga map {a => b: B => (a,b)}
  ap(gb)(pairWithB)
}

您始终可以根据flatMap和pure定义贴图:

def map[A,B](fa: Job[A])(f: A=>B): Job[B] = fa flatMap (f andThen pure)
然后您可以根据地图和平面地图定义ap:

def ap[A,B](fa: => Job[A])(f: => Job[A => B]): Job[B] = 
  fa flatMap { a =>
    f map (_(a))
  }
或与理解糖:

def ap[A,B](fa: => Job[A])(f: => Job[A => B]): Job[B] = 
  for {
    a <- fa
    ff <- f
  } yield ff(a)
def ap[A,B](fa: => Job[A])(f: => Job[A => B]): Job[B] = 
  for {
    a <- fa
    ff <- f
  } yield ff(a)
def ap[A,B](fa: => Job[A])(f: => Job[A => B]): Job[B] =
  fa flatMap { a =>
    f flatMap { ff => pure(ff(a)) }
  }