Skip to content

Instantly share code, notes, and snippets.

@neko-kai
Last active March 12, 2018 16:57
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 neko-kai/729c1f9d0a2d654e1fe67d1394d094f6 to your computer and use it in GitHub Desktop.
Save neko-kai/729c1f9d0a2d654e1fe67d1394d094f6 to your computer and use it in GitHub Desktop.
.fork and .pull for cats Arrow and Function1 (`=>`)
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