Skip to content

Instantly share code, notes, and snippets.

@radium226
Created January 21, 2018 20:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radium226/df24e0c12a9a7e1fa4322596ea4feb33 to your computer and use it in GitHub Desktop.
Save radium226/df24e0c12a9a7e1fa4322596ea4feb33 to your computer and use it in GitHub Desktop.
Free Monad in Scala with Cats
object ImageApp extends App {
import cats._
import cats.free._
import cats.data._
case class Image(bytes: Array[Byte])
sealed trait ImageOp[A] // Image Algebra
case class Open[A](url: String) extends ImageOp[Image]
case class Grayscale[A]() extends ImageOp[Unit]
case class Resize[A](ratio: Double) extends ImageOp[Unit]
type ImageOpF[A] = Free[ImageOp, A]
object ImageOps {
def open(url: String): ImageOpF[Image] = Free.liftF[ImageOp, Image](Open(url))
def grayscale: ImageOpF[Unit] = Free.liftF[ImageOp, Unit](Grayscale())
def resize(ratio: Double): ImageOpF[Unit] = Free.liftF[ImageOp, Unit](Resize(ratio))
}
val imageOpCompiler = new (ImageOp ~> Id) {
def apply[A](imageOp: ImageOp[A]): Id[A] = {
imageOp match {
case Grayscale() =>
println("Converting image to grayscale")
()
case Open(url) =>
println(s"Opening ${url}")
Image(null)
case Resize(ratio) =>
println(s"Resizing image by ${ratio} percent")
()
}
}
}
import ImageOps._
val program: ImageOpF[Unit] = for {
_ <- open("http://tagueule")
_ <- grayscale
u <- resize(0.5)
} yield u
val compiled = program.compile(imageOpCompiler).run
println(compiled)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment