Skip to content

Instantly share code, notes, and snippets.

@nafg
Last active August 29, 2015 14:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nafg/e8af2dc665da77e9e6ba to your computer and use it in GitHub Desktop.
Save nafg/e8af2dc665da77e9e6ba to your computer and use it in GitHub Desktop.
Limitless Applicative builder
trait ApType {
import scala.language.higherKinds
type FS[+Z]
}
trait ApTypeOne[A] extends ApType {
type FS[+Z] = A => Z
}
trait ApTypeMore[A, N <: ApType] extends ApType {
type FS[+Z] = A => N#FS[Z]
}
import scala.language.higherKinds
trait Applicative[M[_]] {
def apply[A, B](f: M[A => B])(a: M[A]): M[B]
def point[A](a: => A): M[A]
}
trait ApBase[M[_], AT <: ApType] {
implicit def m: Applicative[M]
def apply[Z](f: M[AT#FS[Z]]): M[Z]
def applyPoint[Z](f: AT#FS[Z]): M[Z] = apply(m.point(f))
def :@:[B](b: M[B]): ApBase[M, ApTypeMore[B, AT]] = new ApMore[M, B, AT](b, this)
}
implicit class ApOne[M[_], A](val in: M[A])(implicit val m: Applicative[M]) extends ApBase[M, ApTypeOne[A]] {
override def apply[Z](f: M[A => Z]): M[Z] = m.apply(f)(in)
}
class ApMore[M[_], A, N <: ApType](val a: M[A], val next: ApBase[M, N])(implicit val m: Applicative[M]) extends ApBase[M, ApTypeMore[A, N]] {
override def apply[Z](f: M[A => N#FS[Z]]): M[Z] = next.apply(m.apply(f)(a))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment