Suppose I've got a basic DSL defined and have a subprogram type using a couple of them.
import freek._
import cats.{Id, ~>}
object KVStore {
sealed trait DSL[A]
final case class Put[A](key: String, v: A) extends DSL[Unit]
final case class Get[A](key: String) extends DSL[Option[A]]
object Interpreter extends (DSL ~> Id) {
def apply[A](fa: DSL[A]): Id[A] = ???
}
}
object WebIO {
sealed trait DSL[A]
final case class Fetch(key: String) extends DSL[String]
object Interpreter extends (DSL ~> Id) {
def apply[A](fa: DSL[A]): Id[A] = ???
}
}
object FileIO {
sealed trait DSL[A]
final case class Lift[A](value: A) extends DSL[A]
// Interpreter for Lifting.DSL is simple. Just use Applicative.pure
object Interpreter extends (DSL ~> Id) {
def apply[A](fa: DSL[A]): Id[A] = ???
}
}
// The subprogram
object KVStoreWithWeb {
type PRG = KVStore.DSL :|: WebIO.DSL :|: NilDSL
}
Later on, I define another program in which I use the aforementioned subprogram in addition to a yet-unused DSL (FileIO.DSL). I'd like to have a type for my App level `Interpreter, since I might use it in other parts of the app.
// Main program that uses subprogram
object AnotherProgram {
type PRG = FileIO.DSL :|: KVStoreWithWeb.PRG
val PRG = DSL.Make[PRG]
type Interp[M[_]] = Interpreter[PRG.Cop, M]
}
If I try to instantiate an Interp[Id] with the order mixed up, the compiler blows up with an interesting error.
val interpreter: Interp[Id] = KVStore.Interpreter :&: WebIO.Interpreter :&: FileIO.Interpreter
[error] last tree to typer: TypeTree
[error] tree position: line 55 of /Users/Lloyd/Documents/scala_dev/freek-test/test/freeky/App.scala
[error] tree tpe: <error>
[error] symbol: <none>
[error] symbol definition: <none> (a NoSymbol)
[error] symbol package: <none>
[error] symbol owners:
[error] call site: object App in package freeky in package freeky
[error]
[error] == Source file context for tree position ==
[error]
[error] 52 type Interp[M[_]] = Interpreter[PRG.Cop, M]
[error] 53
[error] 54 val interpreter: Interp[Id] = KVStore.Interpreter :&: WebIO.Interpreter :&: Lifting.Interpreter
[error] 55
[error] 56 }
If I fix the ordering to match the DSL type, everything works fine:
val interpreter: Interp[Id] = FileIO.Interpreter :&: KVStore.Interpreter :&: WebIO.Interpreter
Suppose I've got a basic DSL defined and have a subprogram type using a couple of them.
Later on, I define another program in which I use the aforementioned subprogram in addition to a yet-unused DSL (
FileIO.DSL
). I'd like to have a type for myApp
level `Interpreter, since I might use it in other parts of the app.If I try to instantiate an
Interp[Id]
with the order mixed up, the compiler blows up with an interesting error.If I fix the ordering to match the DSL type, everything works fine: