Skip to content

Instantly share code, notes, and snippets.

@jsuereth
Created August 4, 2011 17:33
Show Gist options
  • Save jsuereth/1125710 to your computer and use it in GitHub Desktop.
Save jsuereth/1125710 to your computer and use it in GitHub Desktop.
reason #37 Why macros against Function1->22 would be useful..
trait ApplicativeMagic[F[_]] {
def apply[C](f: ApplicativeMagicFunctionHolder[FunctionArg => C]): F[C]
type FunctionArg
}
class ApplicativeMagicFunctionHolder[F](val f: F)
object ApplicativeMagicFunctionHolder {
implicit def fix2[A,B,C](f: (A,B) => C): ApplicativeMagicFunctionHolder[Tuple2[A,B] => C] =
new ApplicativeMagicFunctionHolder({ case (a,b) => f(a,b) })
implicit def fix3[A,B,C,D](f: (A,B,C) => D): ApplicativeMagicFunctionHolder[Tuple2[Tuple2[A,B],C] => D] =
new ApplicativeMagicFunctionHolder({ case ((a,b),c) => f(a,b,c) })
implicit def fix4[A,B,C,D,E](f: (A,B,C,D) => E): ApplicativeMagicFunctionHolder[Tuple2[Tuple2[Tuple2[A,B],C],D] => E] =
new ApplicativeMagicFunctionHolder({ case (((a,b),c),d) => f(a,b,c,d) })
def apply[A,C](f: A => C) = new ApplicativeMagicFunctionHolder(f)
}
object ApplicativeMagic {
def apply[F[_], A](ma: F[A])(implicit functor: Functor[F]) = new ApplicativeMagic1[F,A](ma)(functor)
}
class ApplicativeMagic1[F[_],A](ma: F[A])(implicit functor: Functor[F]) extends ApplicativeMagic[F] {
import Implicits._
type FunctionArg = A
override def apply[C](f: ApplicativeMagicFunctionHolder[FunctionArg => C]): F[C] = ma map f.f
def <*>[B](mb: F[B]) = new ApplicativeMagicN[F,B,this.type](mb, this)
}
class ApplicativeMagicN[F[_], B, Magic <: ApplicativeMagic[F]](mn: F[B], prev: Magic)(implicit functor: Functor[F]) extends ApplicativeMagic[F] {
import Implicits._
type FunctionArg = (Magic#FunctionArg, B)
override def apply[C](f: ApplicativeMagicFunctionHolder[FunctionArg => C]): F[C] = {
val f2: Magic#FunctionArg => B => C = args => b => f.f((args,b))
mn.fmap(prev[B=>C](ApplicativeMagicFunctionHolder(f2)))
}
def <*>[C](mc: F[C]) = new ApplicativeMagicN[F,C,this.type](mc, this)
}
scala> ApplicativeMagic(Config("hi")) <*> Config("u") <*> Config("guys") apply (java.sql.DriverManager.getConnection _)
res1: com.github.jsuereth.applicative.config.Config[java.sql.Connection] = com.github.jsuereth.applicative.config.FlatMappedConfig@a0ebdfd
/* Note: Config could also be loaded from file/disk etc. It's a combined IO/Reader Monad. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment