Right now, we use a hackish way to compose interpreters wherein we use a big interpreter composed of little interpreters. The big interpreter dispatches to the little specific interpreters:
class AppInstructionInterpreter(logInterpreter: LogInterpreter, dbInterpreter: DatabaseInterpreter) {
val interpreter: AppInstruction ~> Task = new (AppInstruction ~> Task) {
override def apply[A](fa: AppInstruction[A]): Task[A] = fa match {
case logInstruction: LogInstruction[A] =>
logInterpreter.run(logInstruction)
case dbInstruction: DatabaseInstruction[A] =>
dbInterpreter.run(dbInstruction)
}
}
Right now, we use a hackish way to compose interpreters wherein we use a big interpreter composed of little interpreters. The big interpreter dispatches to the little specific interpreters:
Source
The way to merge interpreters properly is to use Coproducts. See here: