Skip to content

Instantly share code, notes, and snippets.

@danclien
Last active August 29, 2015 13:57
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danclien/9800403 to your computer and use it in GitHub Desktop.
Save danclien/9800403 to your computer and use it in GitHub Desktop.
Attempt to write a monad for console IO using scalaz's Free monad
:paste
import scalaz._, Scalaz._, scalaz.Free.{Suspend, Return}
// Console grammar
sealed trait ConsoleF[+A]
object Console {
case class WriteLine[A](msg: String, o: A) extends ConsoleF[A]
case class ReadLine[A](o: String => A) extends ConsoleF[A]
}
// Implement the Functor typeclass for ConsoleF with implicit conversion
implicit def consoleFFunctor[B]: Functor[ConsoleF] = new Functor[ConsoleF]{
import Console._
def map[A,B](fa: ConsoleF[A])(f: A => B): ConsoleF[B] =
fa match {
case ReadLine(h) => ReadLine(x => f(h(x)))
case WriteLine(msg, a) => WriteLine(msg, f(a))
}
}
// Implicit conversion from ConsoleF to the Free monad
implicit def consoleFToFree[A](consolef: ConsoleF[A]): Free[ConsoleF,A] =
Suspend[ConsoleF, A](Functor[ConsoleF].map(consolef)(a => Return[ConsoleF, A](a)))
// Type aliasing
type Console[A] = Free[ConsoleF, A]
// Helper methods for the for-comprehension
object console {
import Console._
def writeLn(msg: String): Free[ConsoleF, Unit] = WriteLine(msg, ())
def readLn(): Free[ConsoleF, String] = ReadLine(v => v)
}
// Create program as data
val program = for {
_ <- console.writeLn("Type in a sentence to echo and hit enter.")
v <- console.readLn()
_ <- console.writeLn("Echoing: " + v)
} yield ()
// Interpreter with side-effects
object ConsoleInterpreter {
import Console._
import scalaz.{~>,Id}, Id.Id
private val exe: ConsoleF ~> Id = new (ConsoleF ~> Id) {
def apply[B](l: ConsoleF[B]): B = l match {
case WriteLine(msg, a) => { println(msg); a }
case ReadLine(h) => { h(readLine()) }
}
}
def apply[A](c: Console[A]): A =
c.runM(exe.apply[Console[A]])
}
// Ctrl-D to exit paste mode
// Run the program
ConsoleInterpreter(program)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment