Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Last active August 29, 2015 14:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/3bb9e80b108359d75d34 to your computer and use it in GitHub Desktop.
Save xuwei-k/3bb9e80b108359d75d34 to your computer and use it in GitHub Desktop.
libraryDependencies += "com.typesafe.play" %% "play" % "2.4.0-M2"
scalaVersion := "2.11.6"
scalacOptions ++= (
"-deprecation" ::
"-unchecked" ::
"-Xlint" ::
"-language:existentials" ::
"-language:higherKinds" ::
"-language:implicitConversions" ::
Nil
)
trait HApply[F[_[_]]] extends HFunctor[F] {
def apply2[A1[_], A2[_], Z[_]](a1: F[A1], a2: F[A2])(f: ({type l[a] = (A1[a], A2[a])})#l ~> Z): F[Z]
def apply3[A1[_], A2[_], A3[_], Z[_]](a1: F[A1], a2: F[A2], a3: F[A3])(f: ({type l[a] = (A1[a], A2[a], A3[a])})#l ~> Z): F[Z] =
apply2[({type l[a] = (A1[a], A2[a])})#l, A3, Z](tuple2(a1, a2), a3)(
new (({type l[a] = ((A1[a], A2[a]), A3[a])})#l ~> Z){
def apply[a](fa: ((A1[a], A2[a]), A3[a])) =
f((fa._1._1, fa._1._2, fa._2))
}
)
def apply4[A1[_], A2[_], A3[_], A4[_], Z[_]](a1: F[A1], a2: F[A2], a3: F[A3], a4: F[A4])(f: ({type l[a] = (A1[a], A2[a], A3[a], A4[a])})#l ~> Z): F[Z] =
apply2[({type l[a] = (A1[a], A2[a])})#l, ({type l[a] = (A3[a], A4[a])})#l, Z](tuple2(a1, a2), tuple2(a3, a4))(
new (({type l[a] = ((A1[a], A2[a]), (A3[a], A4[a]))})#l ~> Z){
def apply[a](fa: ((A1[a], A2[a]), (A3[a], A4[a]))) =
f((fa._1._1, fa._1._2, fa._2._1, fa._2._2))
}
)
def apply5[A1[_], A2[_], A3[_], A4[_], A5[_], Z[_]](a1: F[A1], a2: F[A2], a3: F[A3], a4: F[A4], a5: F[A5])(f: ({type l[a] = (A1[a], A2[a], A3[a], A4[a], A5[a])})#l ~> Z): F[Z] =
apply2[({type l[a] = (A1[a], A2[a])})#l, ({type l[a] = (A3[a], A4[a], A5[a])})#l, Z](tuple2(a1, a2), tuple3(a3, a4, a5))(
new (({type l[a] = ((A1[a], A2[a]), (A3[a], A4[a], A5[a]))})#l ~> Z){
def apply[a](fa: ((A1[a], A2[a]), (A3[a], A4[a], A5[a]))) =
f((fa._1._1, fa._1._2, fa._2._1, fa._2._2, fa._2._3))
}
)
def tuple2[A1[_], A2[_]](a1: F[A1], a2: F[A2]): F[({type l[a] = (A1[a], A2[a])})#l] =
apply2[A1, A2, ({type l[a] = (A1[a], A2[a])})#l](a1, a2)(~>.id[({type l[a] = (A1[a], A2[a])})#l])
def tuple3[A1[_], A2[_], A3[_]](a1: F[A1], a2: F[A2], a3: F[A3]): F[({type l[a] = (A1[a], A2[a], A3[a])})#l] =
apply3[A1, A2, A3, ({type l[a] = (A1[a], A2[a], A3[a])})#l](a1, a2, a3)(~>.id[({type l[a] = (A1[a], A2[a], A3[a])})#l])
def tuple4[A1[_], A2[_], A3[_], A4[_]](a1: F[A1], a2: F[A2], a3: F[A3], a4: F[A4]): F[({type l[a] = (A1[a], A2[a], A3[a], A4[a])})#l] =
apply4[A1, A2, A3, A4, ({type l[a] = (A1[a], A2[a], A3[a], A4[a])})#l](a1, a2, a3, a4)(~>.id[({type l[a] = (A1[a], A2[a], A3[a], A4[a])})#l])
def tuple5[A1[_], A2[_], A3[_], A4[_], A5[_]](a1: F[A1], a2: F[A2], a3: F[A3], a4: F[A4], a5: F[A5]): F[({type l[a] = (A1[a], A2[a], A3[a], A4[a], A5[a])})#l] =
apply5[A1, A2, A3, A4, A5, ({type l[a] = (A1[a], A2[a], A3[a], A4[a], A5[a])})#l](a1, a2, a3, a4, a5)(~>.id[({type l[a] = (A1[a], A2[a], A3[a], A4[a], A5[a])})#l])
}
object HApply {
def apply[F[_[_]]](implicit F: HApply[F]): HApply[F] = F
import play.api.mvc._
import scala.concurrent.Future
implicit val actionBuilderHApply: HApply[ActionBuilder] =
new HApply[ActionBuilder] {
def apply2[A1[_], A2[_], Z[_]](a1: ActionBuilder[A1], a2: ActionBuilder[A2])(f: ({type l[a] = (A1[a], A2[a])})#l ~> Z) =
new ActionBuilder[Z] {
def invokeBlock[C](request: Request[C], block: Z[C] => Future[Result]) =
a1.invokeBlock[C](request, b1 =>
a2.invokeBlock[C](request, b2 =>
block(f((b1, b2)))
)
)
}
def map[A[_], B[_]](fa: ActionBuilder[A])(f: A ~> B): ActionBuilder[B] =
new ActionBuilder[B] {
def invokeBlock[C](request: Request[C], block: B[C] => Future[Result]) =
fa.invokeBlock[C](request, a => block(f(a)))
}
}
}
trait HFunctor[F[_[_]]] {
def map[A[_], B[_]](fa: F[A])(f: A ~> B): F[B]
}
trait ~>[F[_], G[_]] {
def apply[A](fa: F[A]): G[A]
}
object ~> {
def id[F[_]]: F ~> F = new (F ~> F) {
def apply[A](fa: F[A]) = fa
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment