amnaredo / test

0 stars 0 forks source link

Type inference is failing with R/W type classes, scalac gets confused #100

Open amnaredo opened 3 years ago

amnaredo commented 3 years ago

I tried to use upickle R/W as part of interfaces exposed to user. It expects a deal of type inference so that he doesn't repeat himself:

trait Req[I,O]
case class Insert[I : W, O : R](arg: I) extends Req[I,O]
object Problem {
  def execute[I,O](req: Req[I,O]): O = null.asInstanceOf[O]
  val result: Int = execute(Insert("test"))  // both return type and parameter type should be inferred
}

[error] found : String [error] required: Int [error] val result: Int = execute(Insert("test"))

Without W/R type classes it compiles fine. Imho it's a serious problem because:

execute(Append[String,Int,List](...)

ID: 52 Original Author: l15k4

amnaredo commented 3 years ago

Again, I'm afraid this isn't much to do with uPickle specifically; any typeclass based design is going to run into these problems because Scala's type inference isn't perfect. Below, I reproduce the problem using Ordering[T] as a arbitrary dummy-typeclass just to demonstrate the problem. I don't think there's anything I can do specifically in uPickle that will fix it =/

scala> type W[T] = Ordering[T]
defined type alias W

scala> type R[T] = Ordering[T]
defined type alias R

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Req[I,O]
case class Insert[I : W, O : R](arg: I) extends Req[I,O]
object Problem {
  def execute[I,O](req: Req[I,O]): O = null.asInstanceOf[O]
  val result: Int = execute(Insert("test"))  
  // both return type and parameter type should be inferred
}

// Exiting paste mode, now interpreting.

<console>:14: error: type mismatch;
 found   : String
 required: Int
         val result: Int = execute(Insert("test"))  

Original Author: lihaoyi

amnaredo commented 3 years ago

You're right, it should've been a SO question.

Scala type inference in combination with implicit parameter resolution is pretty strange. It is really hard to design an API/Interface with type classes... I must have used path dependent types and "propagate" the type information through outer classes to inner ones.

Original Author: l15k4