ProjectSeptemberInc / freek

Freek, a freaky simple Free to combine your DSL seamlessly
Other
198 stars 19 forks source link

Possible issue with parameterised DSL #2

Closed pvillega closed 11 months ago

pvillega commented 8 years ago

It may be that I'm doing something wrong, but just in case:

I define this DSL and interpreter to Id:

object Http {
  type Parameters = Map[String, List[String]]
  type ErrorMessage = String

  sealed trait DSL[A]
  final case class Get[A: Decoder](url: String, parameters: Parameters) extends DSL[A] {
    val D = implicitly[Decoder[A]]
  }
  final case class Post[A: Decoder](url: String, body: Json) extends DSL[A] {
    val D = implicitly[Decoder[A]]
  }
  final case class Delete[A: Decoder](url: String) extends DSL[A] {
    val D = implicitly[Decoder[A]]
  }
}

object HttpPrinter extends (Http.DSL ~> Id) {
  import Http._

  def apply[A](a: Http.DSL[A]) = {
    println(s"Request > $a")
    defaultStringResponse(a)
  }
}

Using Free from Cats to define helpers:

object Http {
  type PRG[A] = Free[DSL, A]

  def get[A: Decoder](url: String, parameters: Parameters = Map.empty[String, List[String]]): PRG[A] =
    liftF[DSL, A](Get[A](url, parameters))

  def post[A: Decoder](url: String, body: Json): PRG[A] =
    liftF[DSL, A](Post[A](url, body))

  def delete[A: Decoder](url: String): PRG[A] =
    liftF[DSL, A](Delete[A](url))

  val printerInterpreter = HttpPrinter
}

The following tests passes:

class HttpSpec extends FlatSpec with Matchers {

  val testProgram = for {
    g <- get[String](serverUrl)
    p <- post[String](serverUrl, Json.Null)
    d <- delete[String](serverUrl)
  } yield List(g, p, d)

  "Http DSL" should "be executed without error using the printer interpreter" in {
    val result = testProgram.foldMap(printerInterpreter)
    result should be(List("", "", ""))
  }
}

But if I use FreeK helpers:

object Http {
  type HttpPRG[A] = (DSL :|: FXNil)#Cop[A]
  val printerInterpreterFreek: Interpreter[HttpPRG, Id] = HttpPrinter
}

The following test fails to compile:

class HttpSpec extends FlatSpec with Matchers {
  it should "work with FreeK and be executed without error using the printer interpreter" in {
    val testProgram2 = for {
      g <- Get[String](serverUrl, Map.empty[String, List[String]]).freek[HttpPRG]
      p <- Post[String](serverUrl, Json.Null).freek[HttpPRG]
      d <- Delete[String](serverUrl).freek[HttpPRG]
    } yield List(g, p, d)

    val result = testProgram2.interpret(printerInterpreterFreek)
    result should be(List("", "", ""))
  }
}

with error:

Error:(42, 73) could not find implicit value for parameter sub: freek.SubCop[[γ]freek.ConsK[com.perevillega.trades.dsl.Http.Get,freek.CNilK,γ],com.perevillega.trades.dsl.Http.HttpPRG]
      g <- Get[String](serverUrl, Map.empty[String, List[String]]).freek[HttpPRG]
                                                                        ^

I'm importing the si2712fix plugin in my build.sbt:

libraryDependencies ++= Seq(
  "org.spire-math" %% "kind-projector" % kindProjectorVersion,
  "com.milessabin" % "si2712fix-plugin" % si2712fixVersion cross CrossVersion.full,
   ...)

addCompilerPlugin("org.spire-math" %% "kind-projector" % kindProjectorVersion)
addCompilerPlugin("com.milessabin" % "si2712fix-plugin" % si2712fixVersion cross CrossVersion.full)

I tried upcasting to DSL[A] as in the KVS example but didn't work. I may be missing something obvious (in that case, apologies, and what is it?), but just in case it's a real issue... raising it :)

dwhitney commented 8 years ago

Haven't tried it in a compiler, but I think you can solve this by changing this line: g <- Get[String](serverUrl, Map.empty[String, List[String]]).freek[HttpPRG] to g <- Get[String](serverUrl, Map.empty[String, List[String]]).upcast[Http.DSL[String]].freek[HttpPRG]

pvillega commented 8 years ago

I tried that when I reported and didn't work for me, I'll give it a go later again just in case I missed something obvious

On Wed, 15 Jun 2016 at 17:46 dwhitney notifications@github.com wrote:

Haven't tried it in a compiler, but I think you can solve this by changing this line: g <- Get[String](serverUrl, Map.empty[String, List[String]]).freek[HttpPRG] to g <- Get[String](serverUrl, Map.empty[String, List[String]]).upcast[Http[String]].freek[HttpPRG]

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ProjectSeptemberInc/freek/issues/2#issuecomment-226247461, or mute the thread https://github.com/notifications/unsubscribe/AABEvv89xDKFr0cchSJ3FxWSUflG4KVPks5qMCxRgaJpZM4IzzXO .