typelevel / kind-projector

Compiler plugin for making type lambdas (type projections) easier to write
MIT License
919 stars 75 forks source link

Alternative syntax for polymorphic lambdas (for Shapeless) #138

Open yangzai opened 4 years ago

yangzai commented 4 years ago

Currently kind-projector allows

val g = λ[Id ~> Option].run(x => Some(x))

to be rewritten as

val g = new (Id ~> Option) {
  def run[A](x: Id[A]): Option[A] = Some(x)
}

I was wondering if there could be an alternative syntax that rewrites to

object g extends (Id ~> Option) {
  def apply[A](x: Id[A]): Option[A] = Some(x)

// if possible it should allow rewrite to other method names as well:
//  def run[A](x: Id[A]): Option[A] = Some(x)
}

in situations where the singleton type g.type is required.

i.e. in Shapeless

the[Case1.Aux[g.type, Id[Int], Option[Int]]]

should compile.

SethTisue commented 3 years ago

this suggestion doesn't seem to have any attracted much interest. should we leave the ticket open?

dwijnand commented 3 years ago

In

val g = new (Id ~> Option) {
  def run[A](x: Id[A]): Option[A] = Some(x)
}

The static type is Id ~> Option. If you need a singleton type have you seen if the following works?

val gDefn = new (Id ~> Option) {
  def run[A](x: Id[A]): Option[A] = Some(x)
}
val g: gDefn.type = gDefn
the[Case1.Aux[g.type, Id[Int], Option[Int]]]
yangzai commented 3 years ago

@dwijnand nope. I still can't get it to work. I'm testing with:

object Shape extends App {
  import shapeless._
  import shapeless.PolyDefns._

  object G extends (Id ~> Option) {
    def apply[A](x: Id[A]): Option[A] = Some(x)
  }

  val gDefn = new (Id ~> Option) {
//    def run[A](x: Id[A]): Option[A] = Some(x)
    override def apply[T](x: Id[T]): Option[T] = Some(x)
  }
  val g: gDefn.type = gDefn

  the[Case1.Aux[G.type, Id[Int], Option[Int]]] //compiles
  the[Case1.Aux[g.type, Id[Int], Option[Int]]] //does not compile
  the[Case1.Aux[gDefn.type, Id[Int], Option[Int]]] //does not compile
}

Error message:

could not find implicit value for parameter t: shapeless.PolyDefns.Case1.Aux[Shape.g.type,shapeless.Id[Int],Option[Int]]
  the[Case1.Aux[g.type, Id[Int], Option[Int]]] //does not compile