ProjectSeptemberInc / freek

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

Closure and DSL #18

Closed romainreuillon closed 7 years ago

romainreuillon commented 7 years ago

Hi,

freek is amazing. However I am still sucked on a pattern that I am unable to express with freek yet. I'd like to be able to pass an unpure closure that is using an DSL which is undifined at the function definition site but will be determined at the call site. Something like this:

trait DSL1[A]
case object KW1 extends DSL1[Int]

type PRG1 = DSL1 :|: NilDSL
val PRG1 = DSL1.Make[PRG1]

def function[C[_]](closure: Free[C, Int]) =
  for {
    i1 <- KW1.freek[PRG1].expand(????)
    i2 <- closure.expand(???)
  } yield i1 + i2

Do you have an idea how I could express that using freek?

Romain

romainreuillon commented 7 years ago

I tried something like that but it does'nt compile:

  def testCall = {
    type InnerDSL = RNG.PRG :||: Step.PRG
    test(Make[InnerDSL])(Step.get.expand[InnerDSL])
  }

  def test[DSL <: freek.DSL, C[_] <: freek.CopK[_]](m: Make[DSL, C])(f: Free[C, Int])(implicit subdsl1: SubDSL[In1[RNG.DSL,?], DSL]) = {
    for {
      i1 <- RNG.nextInt(10).expand[DSL]
      i2 <- f.expand[DSL]
    } yield i1
  }

I get this error:

[error] /home/reuillon/Documents/Recherche/Projects/models/micmac/src/main/scala/fr/geocites/micmac/dynamic.scala:166: could not find implicit value for parameter subdsl: freek.SubDSL[C,DSL]
[error]       i2 <- f.expand[DSL]
[error]                     ^

Is there a way to make the code simpler K

romainreuillon commented 7 years ago

I found solution by mixing typeclasses on a wrapper type and freek interpreter composition: https://github.com/Geographie-cites/micmac-scala

I am unsure if this pattern should be provided directly using freek constructs or not.

romainreuillon commented 7 years ago

To be more specific, it is illustrated by the function fillPlanes in this file: https://github.com/Geographie-cites/micmac-scala/blob/master/src/main/scala/fr/geocites/micmac/dynamic.scala

mandubian commented 7 years ago

hey, sorry github never notified me on this project notifs :)

have you tried just implicit subdsl1: SubDSL[RNG.DSL.Cop, DSL] ? but DSL :||: DSL2 has still edge-cases that don't work as expected... need to work on that...

mandubian commented 7 years ago

@romainreuillon any comment following my last message?

romainreuillon commented 7 years ago

Actually I took another way using a more scalable (to any number of dsl) approach: https://github.com/ISCPIF/freedsl (soon to be documented)

mandubian commented 7 years ago

Interesting, what is the code generated by the macros? It would be easier for me to understand what it does exactly ;)

romainreuillon commented 7 years ago

There is a small example (a composition of 2 dsl): https://github.com/ISCPIF/freedsl/blob/master/dsl/src/test/scala/freedsl/dsl/DSLTest.scala

They are 2 macros for now. One to generate the case classes in the companion object and one to implement the typeclasses for the wrapping type: https://github.com/ISCPIF/freedsl/blob/master/dsl/src/main/scala/freedsl/dsl/package.scala

If you have idea on how to improve the usability of this lib I would be glad to hear.