Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
minimal cake + tagless final
import cats.data.Chain
// domain layer -----------------------------------------------------------
case class Movie(id: Int, title: String)
trait MovieRepo[F[_]] {
def getMovie(id: Int): F[Option[Movie]]
}
trait UsesMovieRepo[F[_]] {
val movieRepo: MovieRepo[F]
}
trait MovieService[F[_]] extends UsesMovieRepo[F] {
def getMovie(id: Int): F[Option[Movie]] = movieRepo.getMovie(id)
}
// application layer -------------------------------------------------
import monix.eval.Task
val db = Map[Int, Movie](42 -> Movie(42, "A Movie"))
object MovieRepoImpl extends MovieRepo[Task] {
def getMovie(id: Int): Task[Option[Movie]] = Task(db.get(id))
}
trait MixInMovieRepo {
val movieRepo: MovieRepo[Task] = MovieRepoImpl
}
object MovieService extends MovieService[Task] with MixInMovieRepo
val program: Task[Option[Movie]] = MovieService.getMovie(42)
// runtime ------------------------------------------------------
import scala.concurrent.duration._
import scala.concurrent.Await
import monix.execution.Scheduler.Implicits.global
Await.result(program.runToFuture, 1.second)
//Some(Movie(42,A Movie))
// test environment -------------------------------------------------------
import cats.data.Writer
import cats.syntax.writer._
import cats.syntax.option._
type LogWriter[V] = Writer[Chain[String], V]
val logWriterMovieRepo = new MovieRepo[LogWriter] {
def getMovie(id: Int): LogWriter[Option[Movie]] = for {
_ <- Chain(s"getMovie($id)").tell
} yield Movie(id, "Dummy").some
}
object TestMovieService extends MovieService[LogWriter] {
val movieRepo = logWriterMovieRepo
}
TestMovieService.getMovie(42).run
//(Chain(getMovie(42)),Some(Movie(42,Dummy)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment