Skip to content

Commit

Permalink
Initial version of Parallel
Browse files Browse the repository at this point in the history
  • Loading branch information
Luka Jacobowitz committed Aug 21, 2017
1 parent 80a9853 commit 82b6ae7
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
60 changes: 60 additions & 0 deletions core/src/main/scala/cats/Parallel.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cats

trait Parallel[M[_], F[_]] {
def applicative: Applicative[F]
def sequential(implicit M: Monad[M]): F ~> M
def parallel(implicit M: Monad[M]): M ~> F
}

object Parallel {
def parSequence[T[_]: Traverse, M[_]: Monad, F[_], A]
(tma: T[M[A]])(implicit P: Parallel[M, F]): M[T[A]] = {
implicit val F = P.applicative
val fta: F[T[A]] = Traverse[T].traverse(tma)(P.parallel.apply)
P.sequential.apply(fta)
}

def parTraverse[T[_]: Traverse, M[_]: Monad, F[_], A, B]
(ta: T[A])(f: A => M[B])(implicit P: Parallel[M, F]): M[T[B]] = {
implicit val F = P.applicative
val gtb: F[T[B]] = Traverse[T].traverse(ta)(f andThen P.parallel.apply)
P.sequential.apply(gtb)
}

def parSequence_[T[_]: Foldable, M[_]: Monad, F[_], A]
(tma: T[M[A]])(implicit P: Parallel[M, F]): M[Unit] = {
implicit val F = P.applicative
val fu: F[Unit] = Foldable[T].traverse_(tma)(P.parallel.apply)
P.sequential.apply(fu)
}

def parTraverse_[T[_]: Foldable, M[_]: Monad, F[_], A, B]
(ta: T[A])(f: A => M[B])(implicit P: Parallel[M, F]): M[Unit] = {
implicit val F = P.applicative
val gtb: F[Unit] = Foldable[T].traverse_(ta)(f andThen P.parallel.apply)
P.sequential.apply(gtb)
}

def parAp[M[_]: Monad, F[_], A, B](mf: M[A => B])
(ma: M[A])
(implicit P: Parallel[M, F]): M[B] = {
implicit val F = P.applicative
val fb = Applicative[F].ap(P.parallel.apply(mf))(P.parallel.apply(ma))
P.sequential.apply(fb)
}

def parProduct[M[_]: Monad, F[_], A, B](ma: M[A], mb: M[B])
(implicit P: Parallel[M, F]): M[(A, B)] =
parAp(Monad[M].map(ma)(a => (b: B) => (a, b)))(mb)

def parAp2[M[_]: Monad, F[_], A, B, Z](ff: M[(A, B) => Z])
(ma: M[A], mb: M[B])
(implicit P: Parallel[M, F]): M[Z] =
Monad[M].map(parProduct(ma, parProduct(mb, ff))) { case (a, (b, f)) => f(a, b) }

def parMap2[M[_]: Monad, F[_], A, B, C](ma: M[A], mb: M[B])
(f: (A, B) => C)
(implicit P: Parallel[M, F]): M[C] = {
Monad[M].map(parProduct(ma, mb)) { case (a, b) => f(a, b) }
}
}
32 changes: 32 additions & 0 deletions core/src/main/scala/cats/syntax/parallel.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cats.syntax

import cats.{Monad, Parallel, Traverse}

trait parallel {
implicit final def catsSyntaxParallelTraverse[T[_]: Traverse, A]
(ta: T[A]): ParallelTraversableOps[T, A] = new ParallelTraversableOps[T, A] {
override def self = ta

override val typeClassInstance: Traverse[T] = T
}
}




trait ParallelTraversableOps[T[_], A] {

val typeClassInstance : cats.Traverse[T]
def self : T[A]

implicit val T = typeClassInstance

def parTraverse[M[_]: Monad, F[_], B]
(f: A => M[B])(implicit P: Parallel[M, F]): M[T[B]] =
Parallel.parTraverse(self)(f)

def parSequence[M[_]: Monad, F[_], B](implicit ev: A <:< M[B], P: Parallel[M, F]): M[T[B]] =
Parallel.parSequence(self.asInstanceOf[T[M[B]]])


}

0 comments on commit 82b6ae7

Please sign in to comment.