Это продолжение моих предыдущих quesion. Я читаю это post еще раз, чтобы понять дизайн, описанный там.Как определить аппликативный в этом случае?
Вводят монаду Job
, похожую на Haxl. Job[T]
- это операция выборки данных, которая извлекает данные типа T
(и может состоять из других операций, то есть это последовательность выборки данных).
sealed trait Job[+T]
case class PureJob[T](value: T) extends Job[T]
case class BlockedJob[S,T](f: S => Job[T], job: Job[S]) extends Job[T]
case class FetchJob[T](url: Url) extends Job[T]
def pure[T](value: T): Job[T] = PureJob(value)
def flatMap[S,T](f: S => Job[T], job: Job[S]): Job[T] =
job match {
case PureJob(value) => f(value)
case _ => BlockedJob(f, job)
}
Они также ввести функцию 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
к напишите код, как в приведенном выше примере.