Last active
March 12, 2018 16:57
-
-
Save neko-kai/729c1f9d0a2d654e1fe67d1394d094f6 to your computer and use it in GitHub Desktop.
.fork and .pull for cats Arrow and Function1 (`=>`)
This file contains 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
import shapeless._ | |
import shapeless.ops.product._ | |
import shapeless.syntax.std.product._ | |
import cats._ | |
import cats.data._ | |
import cats.arrow._ | |
import cats.syntax.applicative._ | |
import cats.syntax.strong._ | |
import cats.syntax.compose._ | |
import cats.syntax.arrow._ | |
import cats.syntax.profunctor._ | |
import cats.syntax.functor._ | |
import shapeless.ops.tuple._ | |
import java.util.UUID | |
import scala.language.higherKinds | |
object ForkJoinFunctionAndArrow extends LowPriorityImplicits { | |
import cats.instances.all._ | |
implicit class ForkJoinFunctionComplex[A, B <: Product](ab: A => B) { | |
def fork[C](bc: B => C)(implicit append: Prepend[B, Tuple1[C]]): A => append.Out = | |
new ForkJoinArrowComplex(ab).fork(bc)(append) | |
def pull[C](c: C)(implicit append: Prepend[B, Tuple1[C]]): A => append.Out = | |
fork[C](_ => c)(append) | |
} | |
implicit class ForkJoinFunctionStart[A, B](ab: A => B) { | |
def fork[C](bc: B => C): A => (B, C) = { | |
a => | |
val b = ab(a) | |
(b, bc(b)) | |
} | |
def pull[C](c: C): A => (B, C) = ab.andThen((_, c)) | |
} | |
} | |
trait LowPriorityImplicits { | |
// to fix highlighting, defined implicit class for => specifically instead of F | |
implicit class ForkJoinArrowComplex[F[_, _] : Arrow, A, B <: Product](fab: F[A, B]) { | |
def fork[C](fbc: F[B, C])(implicit append: Prepend[B, Tuple1[C]]): F[A, append.Out] = { | |
fab.rmap(x => (x, x)) | |
.>>>(fbc.second[B]) | |
.rmap { | |
case (b, c) => | |
append(b, Tuple1(c)) | |
} | |
} | |
def pull[C](c: C)(implicit append: Prepend[B, Tuple1[C]]): F[A, append.Out] = { | |
fork[C](Arrow[F].lift(_ => c))(append) | |
} | |
} | |
implicit class ForkJoinArrowStart[F[_, _] : Arrow, A, B](fab: F[A, B]) { | |
def fork[C](fbc: F[B, C]): F[A, (B, C)] = { | |
fab.rmap(x => (x, x)) >>> fbc.second | |
} | |
def pull[C](c: C): F[A, (B, C)] = { | |
fork(Arrow[F].lift(_ => c)) | |
} | |
} | |
} | |
object FnExample { | |
import cats.instances.all._ | |
import ForkJoinFunctionAndArrow._ | |
def pipe = {x: Int => x + 1} | |
.pull(9) | |
.fork(x => s"Hey it's $x: result: ") | |
.pull(false) | |
.pull(UUID.randomUUID()) | |
def print = pipe | |
.>>> { | |
case (a, b, str, bool, uuid) => | |
s"$str ${a + b}, bool: $bool, uuid: $uuid" | |
} | |
.>>>(println) | |
.apply(1) | |
} | |
FnExample.pipe | |
FnExample.print | |
object KleisliExample { | |
import cats.instances.all._ | |
import ForkJoinFunctionAndArrow._ | |
def pipe: Kleisli[Eval, Int, Unit] = Kleisli[Eval, Int, Long] {x => Eval.later{ println(s"L$x\n") ; x.toLong } } | |
.pull("Hey") | |
.map(_.map(_.toUpperCase)) | |
.>>>(Kleisli { x => Eval.later(println(x)) }) | |
def print = pipe.apply(1).value | |
} | |
KleisliExample.pipe | |
KleisliExample.print |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment