Skip to content

Instantly share code, notes, and snippets.

@einblicker
Created December 26, 2011 13:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save einblicker/1521202 to your computer and use it in GitHub Desktop.
Save einblicker/1521202 to your computer and use it in GitHub Desktop.
operational monad
object OperationalMonad extends App {
class Operational {
type instr[A] <: { def run: A }
sealed abstract class Program[A] {
def map[B](k: A => B) = flatMap(k andThen Lift.apply)
def flatMap[B](k: A => Program[B]): Program[B] = {
Bind(this, k)
}
def run: A
}
case class Lift[A](x: A) extends Program[A] {
def run = x
}
case class Bind[A, B](m: Program[A], k: A => Program[B]) extends Program[B] {
def run = k(m.run).run
}
case class Instr[A](instr: instr[A]) extends Program[A] {
def run = instr.run
}
implicit def instr2prog[A](instr: instr[A]): Program[A] = Instr(instr)
}
sealed abstract class IO[A] {
def run: A
}
case class PutStr(x: String) extends IO[Unit] {
def run = print(x)
}
case object GetStr extends IO[String] {
def run = Console.readLine
}
def putStr(x: String): IO[Unit] = PutStr(x)
val getStr: IO[String] = GetStr
val io = new Operational {
type instr[A] = IO[A]
}
import io._
def test() = {
val action = for {
x <- getStr
y <- getStr
_ <- putStr(x + y)
} yield ()
action.run
}
test()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment