Skip to content

Instantly share code, notes, and snippets.

@wheaties
Last active August 29, 2015 14:10
Show Gist options
  • Save wheaties/36755570510ccb4bed4e to your computer and use it in GitHub Desktop.
Save wheaties/36755570510ccb4bed4e to your computer and use it in GitHub Desktop.
Dependently Typed Continuation Monad
//for reference
trait Cont[T, R]{ self =>
def apply(f: T => R): R
def map[B](f: T => B): Cont[B, R] = new Cont[B, R]{
def apply(g: B => R): R = self(f andThen g)
}
def flatMap[B](f: T => Cont[B, R]): Cont[B, R] = new Cont[B, R] {
def apply(g: B => R): R = self(f(_)(g))
}
}
object Cont{
def apply[T, R](f: (T => R) => R): Cont[T, R] = new Cont[T, R] {
def apply(g: T => R) = f(g)
}
}
trait DepCont[T] { self =>
def apply(dep: DepFun1[T]): dep.R
def map[B](f: T => B) = new DepCont[B] {
def apply(dep: DepFun1[B]): dep.R = self(dep compose f)
}
def map(f: DepFun1[T]) = new DepCont[f.R] {
def apply(dep: DepFun1[f.R]): dep.R = self(f andThen dep)
}
def flatMap(f: DepFun1[T])(implicit fm: FlatMappable[DepCont, f.R]) = new DepCont[fm.R] {
def apply(g: DepFun1[fm.R]): g.R = self(new DepFun1[T] {
type R = g.R
def apply(x: T) = fm(f(x))(g)
})
}
//who needs both map and flatMap?
def dmap[F](f: F)(implicit fm: ContFM[T, F]): fm.Out = fm(this, f)
}
//This really is just an "IsX" implicit!
trait FlatMappable[C[_], F]{
type R
def apply(f: F): C[R]
}
object FlatMappable{
def apply[C[_],F](implicit fm: FlatMappable[C, F]) = fm
implicit def yes[C[_], R0] = new FlatMappable[C, C[R0]] {
type R = R0
def apply(f: C[R0]) = f
}
}
trait ContFM[T, F]{
type Out
def apply(dc: DepCont[T], f: F): Out
}
object ContFM extends LowPriorityContFM{
def apply[T, R](implicit fm: ContFM[T, R]): Aux[T, R, fm.Out] = fm
type Aux[T, R, Out0] = ContFM[T, R]{ type Out = Out0 }
implicit def flatMap[T, R] = new ContFM[T, DepFun1.Aux[T, DepCont[R]]]{
type Out = DepCont[R]
def apply(self: DepCont[T], f: DepFun1.Aux[T, DepCont[R]]) = new DepCont[R] {
def apply(g: DepFun1[R]): g.R = self(new DepFun1[T] {
type R = g.R
def apply(x: T) = f(x)(g)
})
}
}
}
trait LowPriorityContFM{
implicit def map[T, R] = new ContFM[T, DepFun1.Aux[T, R]] {
type Out = DepCont[R]
def apply(self: DepCont[T], f: DepFun1.Aux[T, R]): DepCont[R] = new DepCont[R] {
def apply(dep: DepFun1[R]): dep.R = self(f andThen dep)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment