Skip to content

Instantly share code, notes, and snippets.

@sscarduzio
Last active December 21, 2015 01:49
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 sscarduzio/27ca166d2a2f0ef10dec to your computer and use it in GitHub Desktop.
Save sscarduzio/27ca166d2a2f0ef10dec to your computer and use it in GitHub Desktop.
Daniel's transformer won't work with future
package test
import scala.util.Try
import scalaz._
import scalaz.std.option._
import scalaz.std.list._
sealed trait CoPConst {
type Point[A]
}
final class |:[F[_], T <: CoPConst] extends CoPConst {
type Point[A] = F[T#Point[A]]
}
final class CCNil extends CoPConst {
type Point[A] = A
}
object CoPConst {
sealed trait CApplicative[C <: CoPConst] {
def point[A](a: A): C#Point[A]
def map[A, B](fa: C#Point[A])(f: A => B): C#Point[B]
}
object CApplicative {
implicit def head[F[_]](implicit F: Applicative[F]): CApplicative[F |: CCNil] = new CApplicative[F |: CCNil] {
def point[A](a: A) = F.point(a)
def map[A, B](fa: F[A])(f: A => B): F[B] = F.map(fa)(f)
}
implicit def corecurse[F[_], C <: CoPConst](implicit P: CApplicative[C], F: Applicative[F]): CApplicative[F |: C] = new CApplicative[F |: C] {
def point[A](a: A) = F.point(P.point(a))
def map[A, B](fa: F[C#Point[A]])(f: A => B): F[C#Point[B]] =
F.map(fa) { ca => P.map(ca)(f) }
}
}
sealed trait CTraverse[C <: CoPConst] {
def traverse[G[_] : Applicative, A, B](ca: C#Point[A])(f: A => G[B]): G[C#Point[B]]
}
object CTraverse {
implicit def head[F[_]](implicit F: Traverse[F]): CTraverse[F |: CCNil] = new CTraverse[F |: CCNil] {
def traverse[G[_] : Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] = F.traverse(fa)(f)
}
implicit def corecurse[F[_], C <: CoPConst](implicit C: CTraverse[C], F: Traverse[F]): CTraverse[F |: C] = new CTraverse[F |: C] {
def traverse[G[_] : Applicative, A, B](fca: F[C#Point[A]])(f: A => G[B]): G[F[C#Point[B]]] = {
F.traverse(fca) { ca =>
C.traverse(ca)(f)
}
}
}
}
sealed trait CJoin[C <: CoPConst] {
def join[A](cca: C#Point[C#Point[A]]): C#Point[A]
}
object CJoin {
implicit def head[F[_]](implicit F: Bind[F]): CJoin[F |: CCNil] = new CJoin[F |: CCNil] {
def join[A](ffa: F[F[A]]) = F.join(ffa)
}
implicit def corecurse[F[_], C <: CoPConst](implicit C: CJoin[C], T: CTraverse[C], F: Applicative[F], B: Bind[F]): CJoin[F |: C] = new CJoin[F |: C] {
def join[A](fcfa: F[C#Point[F[C#Point[A]]]]): F[C#Point[A]] = {
val ffca = F.map(fcfa) { cfa =>
F.map(T.traverse(cfa) { fa => fa }) { cca =>
C.join(cca)
}
}
B.join(ffca)
}
}
}
sealed trait Lifter[F[_], C <: CoPConst] {
def apply[A](fa: F[A]): C#Point[A]
}
object Lifter {
implicit def exacthead[F[_]]: Lifter[F, F |: CCNil] = new Lifter[F, F |: CCNil] {
def apply[A](fa: F[A]): F[A] = fa
}
implicit def head[F[_], C <: CoPConst](implicit P: CApplicative[C], F: Functor[F]): Lifter[F, F |: C] = new Lifter[F, F |: C] {
def apply[A](fa: F[A]): F[C#Point[A]] = F.map(fa) { a => P.point(a) }
}
implicit def corecurse[F[_], G[_], C <: CoPConst](implicit L: Lifter[F, C], G: Applicative[G]): Lifter[F, G |: C] = new Lifter[F, G |: C] {
def apply[A](fa: F[A]): G[C#Point[A]] = G.point(L(fa))
}
}
sealed trait Contains[F[_], C <: CoPConst]
object Contains {
implicit def head[F[_], C <: CoPConst]: Contains[F, F |: C] =
new Contains[F, F |: C] {}
implicit def corecurse[F[_], G[_], C <: CoPConst](implicit C: Contains[F, C]): Contains[F, G |: C] =
new Contains[F, G |: C] {}
}
}
final case class Emm[C <: CoPConst, A](run: C#Point[A]) {
def map[B](f: A => B)(implicit C: CoPConst.CApplicative[C]): Emm[C, B] = Emm(C.map(run)(f))
def flatMap[B](f: A => Emm[C, B])(implicit A: CoPConst.CApplicative[C], B: CoPConst.CJoin[C]): Emm[C, B] =
Emm(B.join(A.map(run) { a => f(a).run }))
}
object Emm {
implicit class ApplicativeSyntax[A](val a: A) extends AnyVal {
def point[C <: CoPConst](implicit C: CoPConst.CApplicative[C]): Emm[C, A] = new Emm(C.point(a))
}
implicit class LiftSyntax[F[_], A](val fa: F[A]) extends AnyVal {
def liftM[C <: CoPConst](implicit L: CoPConst.Lifter[F, C]): Emm[C, A] = new Emm(L(fa))
}
}
//
//object ScalaFutureMonad {
//
// import scala.concurrent.Future
// implicit val ec = scala.concurrent.ExecutionContext.global
//
// implicit val FutureFunctor = new Functor[Future] {
// def map[A, B](a: Future[A])(f: A => B): Future[B] = a map f
// }
//
// implicit val FutureMonad = new Monad[Future] {
// def point[A](a: => A): Future[A] = Future(a)
//
// def bind[A, B](fa: Future[A])(f: (A) => Future[B]): Future[B] = fa flatMap f
// }
//}
// Twitter Future does not implement scalaz.Monad, nor there is an import for that. Got to make one ourselves!
object TwitterFutureMonad {
import com.twitter.util.Future
implicit val FutureFunctor = new Functor[Future] {
def map[A, B](a: Future[A])(f: A => B): Future[B] = a map f
}
implicit val FutureMonad = new Monad[Future] {
def point[A](a: => A): Future[A] = Future(a)
def bind[A, B](fa: Future[A])(f: (A) => Future[B]): Future[B] = fa flatMap f
}
}
// Examples //////////////////////////////////////////////////////////////////
object ScalaFutureTest extends App {
import Emm._
import scala.concurrent.{Future, Await}
import scalaz.std.scalaFuture._
implicit val ec = scala.concurrent.ExecutionContext.global
import scala.concurrent.duration._
type C = Future |: Option |: List |: CCNil
val bam: Emm[C, Int] = {
for {
f <- Future(3).liftM[C]
o <- Option(2).liftM[C]
l <- List(1, 1).liftM[C]
} yield (f + o + l)
}
bam.map { intRes =>
println(intRes)
}
// This won't work because the future has a value of "Nil$" size = 0
// see: https://www.dropbox.com/s/blkilphcoccr9we/Screenshot%202015-12-21%2001.28.19.png?dl=0
Await.result(bam.run, 20 seconds)
}
object TwitterFutureTest extends App {
import Emm._
import com.twitter.util.{Future, Await}
import TwitterFutureMonad._
type C = Future |: Option |: List |: CCNil
val bam = {
for {
f <- Future{Thread.sleep(2000); 3}.liftM[C]
o <- Option(2).liftM[C]
l <- List(1, 1).liftM[C]
} yield (f + o + l)
}
bam.map { intRes =>
println(intRes)
}
// All good, prints 6, 6
Await.result(bam.run)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment