Skip to content

Instantly share code, notes, and snippets.

@kmizu
Created September 25, 2011 14:34
Show Gist options
  • Save kmizu/1240648 to your computer and use it in GitHub Desktop.
Save kmizu/1240648 to your computer and use it in GitHub Desktop.
A naive continuation monad implementation in Scala. It is useless. However, it maybe useful to understand continuation monad.
//This implementation is a porting of naive continuation monad in Haskell in "All About Monads" pages.
class Cont[R, +A](val runCont: (A => R) => R) {
def map[B](f: A => B): Cont[R, B] = {
new Cont[R, B](k => runCont(a => Cont.ret[R, B](f(a)).runCont(k)))
}
def flatMap[B](f: A => Cont[R, B]) :Cont[R, B] = {
new Cont[R, B](k => runCont(a => f(a).runCont(k)))
}
}
object Cont {
type ==>[A,B] = A => Cont[B, Any]
def ret[R, A](a: A) = new Cont[R, A](k => k(a))
def callCC[A, R](f: (A ==> R) => Cont[R, A]): Cont[R, A] = {
new Cont[R, A](k => f(a => new Cont((x:Any) => k(a))).runCont(k))
}
def runCont[A, B](f: A => B)(c: Cont[B, A]) = c.runCont(f)
def when[A](cond: Boolean, cont: => Cont[A, Any]): Cont[A, Any] = {
if(cond) cont else ret[A, Unit](())
}
def id[A](a: A) = a
}
import Cont._, Character._
val fun : Int => String = {n =>
runCont(id[String])(for (
str <- callCC{(exit1: String ==> String) => for (
_ <- when(n < 10, exit1(n.toString));
ns = (n / 2).toString.map(digit(_, 10));
`n'` <- callCC{(exit2: Int ==> String) => for(
_ <- when(ns.length < 3, exit2(ns.length));
_ <- when(ns.length < 5, exit2(n));
_ <- when(ns.length < 7, {
val `ns'` = ns.reverse.map(forDigit(_, 10))
exit1(`ns'`.dropWhile(_ == '0').mkString(""))
})
) yield (0/:ns)(_+_)}
) yield "(ns = " + ns.toList + ") " + `n'`.toString}
) yield "Answer: " + str)
}
println(fun(5))
println(fun(10))
println(fun(100))
println(fun(1000))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment