Created
April 28, 2019 15:58
-
-
Save phderome/9f7ca90193abf6452ae857645a8166c0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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