ProjectSeptemberInc / freek

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

Bug / Wierd behaviour using OnionT #19

Closed romainreuillon closed 7 years ago

romainreuillon commented 7 years ago

Hi,

this code compiles:

import freek._
import cats.implicits._

object Test {
  sealed trait Instruction[T]
  final case class Get() extends Instruction[Int]

  type PRG = Instruction :|: NilDSL
  val PRG =  freek.DSL.Make[PRG]
  type O = Option :&: Bulb

  Get().freek[PRG].onionT[O]
}

but this one doesn't:

import freek._
import cats.implicits._

object Test {
  sealed trait Instruction[T]
  final case class Get() extends Instruction[Seq[Int]]

  type PRG = Instruction :|: NilDSL
  val PRG =  freek.DSL.Make[PRG]
  type O = Option :&: Bulb

  Get().freek[PRG].onionT[O]
}

It raises this error at compile time:

[error] /home/reuillon/Documents/Tmp/testfreek/Test.scala:12: could not find implicit value for parameter lifter2: freek.Lifter2.Aux[Seq[Int],Test.O,Int]
[error]   Get().freek[PRG].onionT[O]
[error]                          ^
[error] one error found

Any idea why?

Cheers, Romain

romainreuillon commented 7 years ago

To provide a bit of context, I am crafting a lib to leverage wrapper types with type classes and freek: https://github.com/ISCPIF/freedsl

It will reduce the boilerplate to define this kind of construct and provide some ready-to-use DSLs. For instance this DSL provide a way to generate random number using the free monad and typeclasses on a wrapper type: https://github.com/ISCPIF/freedsl/blob/master/random/src/main/scala/freedsl/random/Random.scala

Then it can be combined in third party projects such as: https://github.com/Geographie-cites/micmac-scala/blob/master/src/main/scala/fr/geocites/micmac/context.scala

An used here: https://github.com/Geographie-cites/micmac-scala/blob/master/src/main/scala/fr/geocites/micmac/network.scala

I am now trying to integrate the onion to generate type classes supporting onion constructs automatically: https://github.com/ISCPIF/freedsl/blob/master/dsl/src/main/scala/freedsl/dsl/package.scala (the commented implo method).

mandubian commented 7 years ago

@romainreuillon isn't it just because Seq is nothing (neither a Monad or a Traversable in cats implicits)?

romainreuillon commented 7 years ago

Actually I think it shouldn't have to be, since it is just the return type of get. It doesn't represent something which should be part of the oninon. Any way, even using a vector it doesn't work:

[error] /home/reuillon/Documents/Tmp/testfreek/Test.scala:13: could not find implicit value for parameter lifter2: freek.Lifter2.Aux[scala.collection.immutable.Vector[Int],Test.O,Int]
[error]   Get().freek[PRG].onionT[O]
[error]                          ^
[error] one error found
mandubian commented 7 years ago

have you tried just importing import cats.instances.list._, cats.instances.option._ and use Option & List ... I never import all implicits from cats, it's too wide & collides my own implicits too fast

romainreuillon commented 7 years ago

Yes, the result is the same. It works perfectly when the return type of get is not higher kinded. What I want it that the onion function considers get return type as being Id[Seq[Int]] in:

import freek._
import cats.implicits._

object Test {
  sealed trait Instruction[T]
  // Seq[Int] doesn't represent and error but is the return type of Get
  final case class Get() extends Instruction[Seq[Int]]

  type PRG = Instruction :|: NilDSL
  val PRG =  freek.DSL.Make[PRG]
  type O = Option :&: Bulb

  Get().freek[PRG].onionT[O]
}

the same manner it considers get as return type of type Id[Int] here:

import freek._
import cats.implicits._

object Test {
  sealed trait Instruction[T]
  // Return type of get is Int here
  final case class Get() extends Instruction[Int]

  type PRG = Instruction :|: NilDSL
  val PRG =  freek.DSL.Make[PRG]
  type O = Option :&: Bulb

  Get().freek[PRG].onionT[O]
}
mandubian commented 7 years ago
import cats._
    import cats.free.Free
    import cats.implicits._

    import freek._

    object Test {
      sealed trait Instruction[T]
      // Seq[Int] doesn't represent and error but is the return type of Get
      final case class Get() extends Instruction[List[Int]]

      type PRG = Instruction :|: NilDSL
      val PRG =  freek.DSL.Make[PRG]
      type O = Option :&: List :&: Bulb

      Get().freek[PRG].onionT[O]
    }

That compiles on my MBP...

romainreuillon commented 7 years ago

Good, but maybe I misunderstood, but I don't want the list to be composed in the onion. It is just a return type. I want it to be considered as a simple type.

mandubian commented 7 years ago

ah :) for that, you have .onion[PRG] .onionT[PRG] tried to get all types and put them into the onion... there are other helpers for weirder cases but I haven't documented them yet because I'm not sure about their names & usefulness!

romainreuillon commented 7 years ago

Thx a lot, it works like a charm! Freek is awsome!

mandubian commented 7 years ago

you're welcome ;)

romainreuillon commented 7 years ago

I cannot understand what's happening, if I use onion it doesn't work with simple types:

  sealed trait Instruction[T]
  final case class GetH() extends Instruction[Set[Int]]
  final case class Get() extends Instruction[Int]

  type PRG = Instruction :|: NilDSL
  val PRG =  freek.DSL.Make[PRG]
  type O = Option :&: Bulb

  Get().freek[PRG].onion[O]
  GetH().freek[PRG].onion[O]

The error is:

[error] /home/reuillon/Documents/Tmp/testfreek/Test.scala:15: value onion is not a member of cats.free.Free[[t]freek.In1[Test.Instruction,t],Int]
[error]   Get().freek[PRG].onion[O]
[error]                    ^
[error] one error found
romainreuillon commented 7 years ago

And it doesn't work, even I wrap the Int in Id:

  final case class Get() extends Instruction[Id[Int]]
romainreuillon commented 7 years ago

Finally I found the thing I was looking for, it was .onionX1.

mandubian commented 7 years ago

Cool... there are a few helpers not very documented ;) If you find other cases not solved by those helpers, don't hesitate to report them!