Skip to content

Instantly share code, notes, and snippets.

@lamdor
Created September 15, 2016 13:28
Show Gist options
  • Save lamdor/777693ee57b3f0389ffb8afafa62bfec to your computer and use it in GitHub Desktop.
Save lamdor/777693ee57b3f0389ffb8afafa62bfec to your computer and use it in GitHub Desktop.
package learn
import java.io.File
import cats.{~>, Id}
import cats.free.Free
import cats.data.Xor
import cats.instances.option._
import freek._
import scala.concurrent.Future
object Log {
sealed trait LogLevel
case object DebugLevel extends LogLevel
case object InfoLevel extends LogLevel
case object WarnLevel extends LogLevel
case object ErrorLevel extends LogLevel
trait DSL[A]
final case class LogMsg(level: LogLevel, msg: String) extends DSL[Unit]
def debug(msg: String) = LogMsg(DebugLevel, msg)
def info(msg: String) = LogMsg(InfoLevel, msg)
def warn(msg: String) = LogMsg(WarnLevel, msg)
def error(msg: String) = LogMsg(ErrorLevel, msg)
}
object KVS {
trait DSL[A]
final case class Get(key: String) extends DSL[Option[String]]
final case class Put(key: String, value: String) extends DSL[Unit]
}
object FileIO {
trait DSL[A]
final case class GetFile(path: String) extends DSL[String Xor File]
final case class WriteFile(path: String, contents: String) extends DSL[Unit]
final case class DeleteFile(path: String) extends DSL[Unit]
}
object WritingFilesProgram {
type PRG = Log.DSL :|: KVS.DSL :|: FileIO.DSL :|: NilDSL
val PRG = DSL.Make[PRG]
type O = Xor[String, ?] :&: Option :&: Bulb
def getAndWrite(path1: String, path2: String): OnionT[Free, PRG.Cop, O, File] =
for {
aStr <- KVS.Get(path1).freeko[PRG, O]
bStr <- KVS.Get(path2).freeko[PRG, O]
combinedPath = "combined"
_ <- Log.info(s"writing to file '$combinedPath'").freeko[PRG, O]
_ <- FileIO.WriteFile(combinedPath, aStr + bStr).freeko[PRG, O]
f <- FileIO.GetFile(combinedPath).freeko[PRG, O]
} yield f
}
object MockIdInterpreters {
val LogInterpreter = new (Log.DSL ~> Id) {
def apply[A](log: Log.DSL[A]): Id[A] = log match {
case Log.LogMsg(level, msg) =>
println(s"$level - ${msg}")
}
}
val KVSInterpreter = new (KVS.DSL ~> Id) {
import KVS._
def apply[A](dsl: DSL[A]): Id[A] = dsl match {
case Get(key) => Some("mock")
case Put(key, value) => ()
}
}
val FileIOInterpreter = new (FileIO.DSL ~> Id) {
import FileIO._
def apply[A](dsl: DSL[A]): Id[A] = dsl match {
case GetFile(path) => Xor.right(new File(path))
case WriteFile(path, contents) =>
println(s"MOCK - writing '$contents' to '$path'")
case DeleteFile(path) =>
println(s"MOCK - deletintg to '$path'")
}
}
}
object UsingMockIdInterpreters extends App {
import WritingFilesProgram._
import MockIdInterpreters._
val interpreter = LogInterpreter :&: FileIOInterpreter :&: KVSInterpreter
val result: Xor[String, Option[File]] =
getAndWrite("path1", "path2")
.value
.interpret(interpreter)
println(s"result = ${result}")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment