Skip to content

unhelpful existentials refuse to get out of the way #8936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
scabug opened this issue Oct 23, 2014 · 5 comments
Closed

unhelpful existentials refuse to get out of the way #8936

scabug opened this issue Oct 23, 2014 · 5 comments
Assignees

Comments

@scabug
Copy link

scabug commented Oct 23, 2014

Another in the thrilling series of language features which require the application of rocket science just to get them to leave you alone. All I want is the class object, must it be so hard? See also #8039 for what is in some sense the dual nightmare.

class A {
  // Splitting out the implicit class doesn't help.
  implicit class Foo[A](x: A) { def bar(f: A => Seq[A]) = f(x) }

  // Okay, fair enough this doesn't work. Overly specific type is
  // inferred and then dooms us later.
  def f1 = classOf[List[_]] bar (_.getInterfaces.toSeq)
  // a.scala:4: error: type mismatch;
  //  found   : Seq[Class[_]]
  //  required: Seq[Class[List[_]]]
  //   def f1 = classOf[List[_]] bar (_.getInterfaces.toSeq)
  //                                                  ^

  // Apparently Class[_] is STILL too specific. Can anyone suggest a
  // less specific type which is still a Class?
  def f2 = (classOf[List[_]] : Class[_]) bar (_.getInterfaces.toSeq)
  //  found   : Seq[Class[_]]
  //  required: Seq[Class[_$3]] where type _$3
  //   def f2 = (classOf[List[_]] : Class[_]) bar (_.getInterfaces.toSeq)
  //

  // Giving it a type parameter home doesn't help either.
  def f3[A](x: Class[A]) = x bar (_.getInterfaces.toSeq)
  // found   : Seq[Class[_]]
  // required: Seq[Class[A]]
  //  def f3[A](x: Class[A]) = x bar (_.getInterfaces.toSeq)
  //                                                  ^

  // At this point we've blown way past the "worth the trouble"
  // boundary, but for the record it compiles this way.
  def f4 = new Foo[Class[_]](classOf[List[_]]) bar (_.getInterfaces.toSeq)
}
@scabug
Copy link
Author

scabug commented Oct 23, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8936?orig=1
Reporter: @paulp

@scabug
Copy link
Author

scabug commented Oct 23, 2014

@paulp said:
The key question is why/how f2 is not equivalent to f4.

@scabug
Copy link
Author

scabug commented Oct 23, 2014

@paulp said:
And if you're tempted to suggest something like

  implicit class Foo[A](x: A) { def bar[A1 >: A](f: A => Seq[A1]) = f(x) }

The problem is that this method is called repeatedly/recursively.

@scabug
Copy link
Author

scabug commented Nov 1, 2014

@retronym said (edited on Nov 1, 2014 12:15:49 PM UTC):
Let's look at through this example. I'm avoiding the placeholder syntax for existentials to highlight the different types.

trait C[A] { def bar(f: A => A) }

trait M[A] { def m: M[Y] forSome { type Y } = ??? }

object Test {
  def c[A](a: A): C[A] = ???

  def x1(m: M[Int]) = c/*[M[Int]]]*/(m).bar(_.m) // found M[Y] where type Y, required M[Int]

  def x2(m: M[Int]) = c/*[M[X]]]*/(m : M[X] forSome { type X }).bar(_.m) //found M[Y] where type Y, required M[X] where type X

  def x3(m: M[Int]) = c[M[Z] forSome {type Z}](m).bar(_.m)
}

I don't believe that you can provide an argument to method c that will lead to inference of the type argument explicitly provided in x3, which is the only one that will end up allowing _.m to typecheck.

@scabug scabug closed this as completed Nov 1, 2014
@scabug
Copy link
Author

scabug commented Nov 1, 2014

@paulp said:
I take it you mean "don't believe that you CAN provide an argument to method c..."

It seems you are correct. It would need to leave some slack in the first type inferred for the second one ever to conform to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants