Skip to content
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

Const type inference glitch #1608

Open
kailuowang opened this issue Apr 17, 2017 · 3 comments
Open

Const type inference glitch #1608

kailuowang opened this issue Apr 17, 2017 · 3 comments

Comments

@kailuowang
Copy link
Contributor

kailuowang commented Apr 17, 2017

Const's phantom type can cause some type inference difficulty in scalac. Here is a minimized example:

   def trav[F[_], A, B](f: A => F[B]): F[B] = ???
    case class Const[A, B](a: A)
    val c: Const[Int, Int] = trav(Const(_:Int))   //compiles
    val a: Int  = trav(Const(_:Int)).a    //doesn’t compile

[error] found : Int => Const[Int,Nothing]
[error] required: Int => Const[Int,B]
[error] val a: Int = trav(Const(_:Int)).a

Making the phantom type covariant will helped the type inference but it's not a very obviously sound solution. See the discussion here by @ceedubs , here by @djspiewak and here by @johnynek.

Shall we live with the type inference inconvenience (not encountered very often though) or the possible ramifications of unnecessarily making the phantom type covariant?

It seems to me that neither incurs significant cost to pay but the former solution is easier to understand.

@smarter
Copy link
Contributor

smarter commented Apr 23, 2017

FWIW, this works:

object Foo {
  type MyNothing >: Nothing <: Nothing
}

case class Const[A, B >: Foo.MyNothing](a: A)

object Test {
  def trav[F[_], A, B](f: A => F[B]): F[B] = ???

  val c: Const[Int, Int] = trav(Const(_:Int))   //compiles
  val a: Int  = trav(Const(_:Int)).a    //compiles too!
}

(The original example also compiles with dotty which does not suffer from nilophobia)

@johnynek
Copy link
Contributor

To me, this is not such a big deal. There are many areas where scala's type inference is not great. In such cases, you sometimes have to use type parameters (or in case matching, even introduce methods for the sole purpose of naming all the type parameters on the matched class, especially in cases with variance).

This seems to me like a case of "don't do that". Certainly making Const covariant seems like the cure being worse than the disease.

@kailuowang
Copy link
Contributor Author

@johnynek covariant is indeed a bit risky, but what about the technique above by @smarter , that seems harmless?

@kailuowang kailuowang modified the milestones: 1.0.0-RC1, 1.0.0-MF May 25, 2017
@kailuowang kailuowang removed this from the 1.0.0-RC1 milestone Aug 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants