-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Crazy Idea: Eliminate the syntax
imports
#4057
Comments
def foo[F[_]: Functor](fa: F[Int]) = fa.map(_ + 1) This already works in Scala 3 without an import thanks to this:
From: https://docs.scala-lang.org/scala3/reference/contextual/extension-methods.html |
I think another approach is to put an |
Doesn't that only work if you import |
I think it doesn't work because it causes confusion with |
Oh I see you were relying on the name collision. Yeah I think that it straight-up conflicts with the companion object, even ignoring |
I think this is too clever personally... I think the import isn't such a tax and I don't see a good trade in complicating the typeclasses to enable this hack. There is also the issue that implicit conversion via function is actually on the way out, and instead we would need to extend |
|
In fact, using (not defining) import scala.language.implicitConversions So, um, what's your grand plan for that one? :P |
Somebody hold me back, I'm on a roll! ……… Okay this is probably a dumb idea. |
FYI more reading here: typelevel/spotted-leopards#9 (comment) |
Okay hear me out…
This only works if we have the
import cats.syntax.all._
(or one of the variations thereof) in scope. Why is that exactly? It's because we need an implicit conversionF[Int] => FunctorOps[F, Int]
, and that exists within theFunctorSyntax
trait which is folded intoAllSyntax
, etc etc etc. Getting an implicit conversion into scope requires an implicit value of typeFunction1
with the appropriately matching types, and that definitely feels like something that's going to require an import one way or another.But we're overlooking something: we already have an implicit instance in scope, by definition:
Functor
itself. If we could defineFunctor[F] <: (F[Int] => FunctorOps[F, Int])
, then this would actually solve the problem! The compiler would consider the implicitFunction1
value to be a valid implicit conversion, thus surfacing themap
syntax and allowing us to proceed forward.Unfortunately, the way I wrote the types above already hints at the problem: we don't want this for
F[Int]
, but ratherF[A]
for allA
. Scala 3 at least has a syntax for expressing this:Functor[F] <: ([A] ==>> F[A] => FunctorOps[F, A])
. Scala 2 has no such syntax, and honestly I'm not sure if Scala 3 is even going to behave correctly in this scenario. We should find out!So there are two experiments here. First, try this out on Scala 3 and see if it works properly. If it does, then we can probably build some parallel subtyping in the
Ops
hierarchy to make it possible to refine the inheritance, allowing each typeclass to extend the conversion to its corresponding syntax. This might run into problems withMonadError
and a few other cases, but we can probably work around that. If Scala 3 resolves this correctly as a universally-quantified implicit conversion, then we have something that at least is workable in https://github.com/typelevel/spotted-leopards (heads up @mpilquist).The Scala 2 side of the house will be a lot more challenging. Realistically this is going to require some sort of weird implicit whitebox macro which materializes an implicit
Function1
which is specialized to the appropriate call-site type. That feels vaguely doable, but it's going to need some poking and prodding.As a final note, this obviously only works when being entirely parametric (since this is when you're explicitly putting the implicit value into scope). Cases like
1 |+| 2
are still going to require a syntax import, barring anything really miraculous. Most notably, so willtraverse
and a few other really common operators. Even still, I think this could be a real step forward.The text was updated successfully, but these errors were encountered: