Interpreter implementation based on scalaz and cats inspired by Rúnar Bjarnason Compositional Application Architecture With Reasonably Priced Monads.
Code based on scalaz and cats is almost the same except dependencies. Full examples are in tests.
Programs for interpretation in general look like this one:
class ImplicitsTest extends FlatSpec with Matchers {
"Implicit conversions" should "be used in the building of a programs" in {
import com.github.nikdon.interpreter.scalaz.Implicits._
// import com.github.nikdon.interpreter.cats.Implicits._
def program[F[_]](implicit
T1: Inject[EnglishSyntax, F],
T2: Inject[JapaneseSyntax, F],
T3: Inject[ChineseSyntax, F]) = for {
_ ← English.Say("The one says: 'Hi!'")
_ ← Japanese.Say("Another one says: 'こんにちは'!")
_ ← Chinese.Say("And somebody says: '嗨!'")
} yield ()
type App[A] = Coproduct[EnglishSyntax, JapaneseSyntax, A]
type App1[A] = Coproduct[ChineseSyntax, App, A]
val prg: Free[App1, Unit] = program[App1]
val engJpInterpreter: App ~> Id = EnglishInterpreter or JapaneseInterpreter
val chEngJpInterpreter: App1 ~> Id = ChineseInterpreter or engJpInterpreter
prg.foldMap(chEngJpInterpreter)
}
}
Another way to create an interpreter is to use HList
from shapeless:
val interpreter: App1 ~> Id = Fold(
(ChineseInterpreter: ChineseSyntax ~> Id) ::
(EnglishInterpreter: EnglishSyntax ~> Id) ::
(JapaneseInterpreter: JapaneseSyntax ~> Id) :: HNil
)
Or Fold.tupleN()
function:
val interpreter: App1 ~> Id = Fold.tupleN(
ChineseInterpreter: ChineseSyntax ~> Id,
EnglishInterpreter: EnglishSyntax ~> Id,
JapaneseInterpreter: JapaneseSyntax ~> Id
)
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.nikdon" % "scalaz-interpreter" % "10630f3ca8"