Skip to content

Contravariant typeclasses and specificity for Nothing were not yet good enough for ourselves? #4465

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
1 task
Blaisorblade opened this issue May 5, 2018 · 6 comments

Comments

@Blaisorblade
Copy link
Contributor

Blaisorblade commented May 5, 2018

Apparently, for contravariant typeclasses, an instance for Nothing is ambiguous with instances for List[T] and Option[T]. That blocks instance resolution for something as simple as List().
I'm not sure whether this is an issue with the spec or with the implementation; I suppose this was an oversight. But it's enough to make instance resolution for Show unusable for us, so much that in #4437 people are proposing to drop Show altogether (also for unrelated reasons). Here's the puzzler:

trait Show[-T] { def show(x: T): String; def instName: String }
implicit def showOption[T]: Show[Option[T]] = new Show { def show(x: Option[T]) = "showOption"; def instName = "showOption" } // XXX
scala> implicitly[Show[Nothing]].instName
val res5: String = "showOption"
scala> implicit def showNothing: Show[Nothing] = new Show[Nothing] { def show(x: Nothing) = ""; def instName = "showNothing" }
implicit val showNothing: Show[Nothing]
scala> implicitly[Show[Nothing]].instName
val res6: String = "showNothing"
scala> implicit def showList[T]: Show[List[T]] = new Show { def show(x: List[T]) = "showList"; def instName = "showList" } // XXX
implicit val showList[T] => Show[List[T]]
scala> implicitly[Show[Nothing]].instName
1 |implicitly[Show[Nothing]].instName
  |                         ^
  |ambiguous implicit arguments: both method showList and method showNothing match type Show[Nothing] of parameter ev of method implicitly in object DottyPredef
  • also investigate covariant and instances for Any, regardless that it's maybe less of a problem
@Blaisorblade
Copy link
Contributor Author

/cc @alexknvl @OlivierBlanvillain

@Blaisorblade
Copy link
Contributor Author

Still same behavior after merging #4329.

@Blaisorblade
Copy link
Contributor Author

OTOH, either before or after #4329 and with or without showNothing, resolution for List() works now:

scala> implicitly[Show[List[Nothing]]].instName
val res2: String = showList
scala> implicitly[Show[Option[Nothing]]].instName
val res3: String = showOption
scala> def show[T: Show](t: T) = implicitly[Show[T]].show(t)
def show[T](t: T)(implicit evidence$1: Show[T]): String
scala> show(List())
val res4: String = showList
scala> show(None)
val res1: String = showOption
scala> show(Some(1))
val res2: String = showOption
scala> show(Nil)
val res3: String = showList
scala> show(1 :: Nil)
val res4: String = showList

@Blaisorblade Blaisorblade self-assigned this May 7, 2018
@Blaisorblade Blaisorblade changed the title Contravariant typeclasses and specificity for Nothing are not yet good enough for ourselves Contravariant typeclasses and specificity for Nothing were not yet good enough for ourselves? May 7, 2018
@Blaisorblade
Copy link
Contributor Author

New plan: ensure all of this is sufficiently tested, and cross-check with Scalac tests.

@OlivierBlanvillain
Copy link
Contributor

So what are we missing here? A spec for the current behavior? I'm not sure where would be the best place to put that, but the comment in isAsSpecificValue seems to be the best documentation we have at the moment.

@Blaisorblade
Copy link
Contributor Author

I wanted to get back to this, but I'm not sure there is a real problem any more (per #4465 (comment)). In doubt, I should probably close this — feel free to reopen and reassign.

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

2 participants