Skip to content

Instantly share code, notes, and snippets.

@phderome
Created April 28, 2019 15:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phderome/9f7ca90193abf6452ae857645a8166c0 to your computer and use it in GitHub Desktop.
Save phderome/9f7ca90193abf6452ae857645a8166c0 to your computer and use it in GitHub Desktop.
package com.fantasy.seed
import cats.{Apply, Functor, FunctorFilter, Invariant, Semigroupal}
import cats.implicits._
import monix.reactive._
trait Collector[F[_]] extends Apply[F] with FunctorFilter[F] {
def map[A, B, Z](fa: F[A], fb: F[B], f: Function1[(A, B), Z])(implicit inv: Invariant[F],
semi: Semigroupal[F]): F[Z] =
map((fa, fb).tupled)(f)
def map[A, B, C, Z](fa: F[A], fb: F[B], fc: F[C], f: Function1[(A, B, C), Z])(implicit inv: Invariant[F],
semi: Semigroupal[F]): F[Z] =
map((fa, fb, fc).tupled)(f)
def mapFilter[A, Z](fa: F[A], p: A => Boolean, f: A => Z)(implicit ff: FunctorFilter[F]): F[Z] =
fa.collect { case x if p(x) => f(x) }
def mapFilter[A, B, Z](fa: F[A], fb: F[B], p: Function1[(A, B), Boolean], f: Function1[(A, B), Z])(
implicit inv: Invariant[F],
semi: Semigroupal[F],
ff: FunctorFilter[F]): F[Z] =
(fa, fb).tupled.collect { case x if p(x) => f(x) }
def mapFilter[A, B, C, Z](fa: F[A], fb: F[B], fc: F[C], p: Function1[(A, B, C), Boolean], f: Function1[(A, B, C), Z])(
implicit inv: Invariant[F],
semi: Semigroupal[F],
ff: FunctorFilter[F]): F[Z] =
(fa, fb, fc).tupled.collect { case x if p(x) => f(x) }
}
object Collector {
def apply[F[_]](implicit ev: Collector[F]): Collector[F] = ev
object syntax {
implicit class CollectorOps[F[_], A](fa: F[A]) {
def map[B, Z](fb: F[B])(f: Function1[(A, B), Z])(implicit ev: Collector[F]): F[Z] =
ev.map(fa, fb, f)
def map[B, C, Z](fb: F[B], fc: F[C])(f: Function1[(A, B, C), Z])(implicit ev: Collector[F]): F[Z] =
ev.map(fa, fb, fc, f)
def mapFilter[Z](p: A => Boolean, f: A => Z)(implicit ev: Collector[F]): F[Z] =
ev.mapFilter(fa, p, f)
def mapFilter[B, Z](fb: F[B])(p: Function1[(A, B), Boolean], f: Function1[(A, B), Z])(
implicit ev: Collector[F]): F[Z] =
ev.mapFilter(fa, fb, p, f)
def mapFilter[B, C, Z](fb: F[B], fc: F[C])(p: Function1[(A, B, C), Boolean], f: Function1[(A, B, C), Z])(
implicit ev: Collector[F]): F[Z] =
ev.mapFilter(fa, fb, fc, p, f)
}
}
implicit val observableCollector: Collector[Observable] = new Collector[Observable] {
def ap[A, B](ff: Observable[A => B])(fa: Observable[A]): Observable[B] =
ff.flatMap(f => fa map f)
def map[A, B](fa: Observable[A])(f: A => B): Observable[B] = fa map f
val functor: Functor[Observable] = new Functor[Observable] {
def map[A, B](fa: Observable[A])(f: A => B): Observable[B] = fa map f
}
val functorFilter: FunctorFilter[Observable] = new FunctorFilter[Observable] {
def functor: Functor[Observable] = new Functor[Observable] {
def map[A, B](fa: Observable[A])(f: A => B): Observable[B] = fa map f
}
def mapFilter[A, B](fa: Observable[A])(f: A => Option[B]): Observable[B] =
fa.map(f).collect { case Some(x) => x } // define it but don't use it, use collect directly instead
}
def mapFilter[A, B](fa: Observable[A])(f: A => Option[B]): Observable[B] =
functorFilter.mapFilter(fa)(f)
// we override mapFilter because we expect the Monix implementation is optimal
override def mapFilter[A, Z](oba: Observable[A], p: Function1[A, Boolean], f: Function1[A, Z])(
implicit ff: FunctorFilter[Observable]): Observable[Z] =
oba.collect { case x if p(x) => f(x) }
override def mapFilter[A, B, Z](oba: Observable[A],
obb: Observable[B],
p: Function1[(A, B), Boolean],
f: Function1[(A, B), Z])(implicit inv: Invariant[Observable],
semi: Semigroupal[Observable],
ff: FunctorFilter[Observable]): Observable[Z] =
(oba, obb).tupled.collect { case x if p(x) => f(x) }
override def mapFilter[A, B, C, Z](oba: Observable[A],
obb: Observable[B],
obc: Observable[C],
p: Function1[(A, B, C), Boolean],
f: Function1[(A, B, C), Z])(implicit inv: Invariant[Observable],
semi: Semigroupal[Observable],
ff: FunctorFilter[Observable]): Observable[Z] =
(oba, obb, obc).tupled.collect { case x if p(x) => f(x) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment