-
Notifications
You must be signed in to change notification settings - Fork 21
Type Inference Issue with Compound Types #11898
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
Comments
That sounds like an artifact of the typechecking algorithm:
|
That sounds about right -- there's no reason that val live: ZLayer[Has[A] with Has[B], Nothing, Has[C]] =
ZLayer.fromServices[A, B, C] { (a, b) =>
new C {}
} is only slighly more verbose (and you could kinda-curry the |
I agree that specifying the type parameters is not that bad, but what is really strange to me is that if I use an intermediate value it also works: val live: ZLayer[Has[A] with Has[B], Nothing, Has[C]] = {
val layer = ZLayer.fromServices { (a: A, b: B) =>
new C {}
}
layer
} If I don't provide any information about the expected type it infers the return type as |
You are still specifying the argument types explicitly and only |
Because Scala's being "helpful" here and trying to use the expected type (derived from the declared result type) to guide type inference, outside-in. If you have no expected type then it has to go inside-out, by typing the argument to |
It's a combination of several things:
This particular example could be fixed with some extra adhoc rules, but I don't think there's a general solution to this problem. One way forward would be to clearly specify and implement ways to guide type inference, for example using type aliases, e.g. the following works in scalac and dotty: trait Has[A]
trait A
trait B
trait C
trait ZLayer[-RIn, +E, +ROut]
object ZLayer {
type ZLayer2[-RIn1, -RIn2, +E, +ROut] = ZLayer[RIn1 with RIn2, E, ROut]
def fromServices[A0, A1, B](f: (A0, A1) => B): ZLayer2[A0, A1, Nothing, Has[B]] =
???
}
object Test {
val live: ZLayer.ZLayer2[A, B, Nothing, Has[C]] =
ZLayer.fromServices { (a: A, b: B) =>
new C {}
}
} It works because when checking |
You could achieve the same effect by specifying a type alias for But beware, it's a leaky abstraction: #10506 |
Yeah, that's why I put the type alias at the top-level, because that ensures we'll compare the aliases first, before any dealiasing. |
@smarter Thank you! That is an interesting suggestion. Shall we close this issue then? |
I managed to find a solution for dotty, but I don't know how hard it'd be to adapt it to scalac: scala/scala3#8635 |
The text was updated successfully, but these errors were encountered: