Last active
August 29, 2015 14:10
-
-
Save wheaties/36755570510ccb4bed4e to your computer and use it in GitHub Desktop.
Dependently Typed Continuation Monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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