I keep hitting this wart where I expect to be able to use type lambdas with placeholders for higher kinded types, but I can never seem to make it work:
For context bounds, I would like to be able to write something like this:
def foo[F[_]: EitherT[*[_], String, Int] = ???
It seems like this case is simply not supported in Scala 3 at the moment?
I read this section Kind Projector Migration | Scala 3 Migration Guide | Scala Documentation from the docs, but the wording here is a bit difficult to decipher.
Is this use case going to be covered in the future, or do we have to explicitly write out the type lambdas for these cases?
1 Like
I am not sure I understand what you want (which is probably a good reason not to have special syntax for this): Can you write down the type lambda you want *[_]
to expand to?
It would be something like:
def foo[F[_]: [G[_]] =>> EitherT[G, String, Int]] = ???
which I personally find equally hard to read/understand. Not sure if it would be possible, but preferrably, I would love it if the compiler could just understand from the context that the placeholder needs to be higher kinded such that I could just write:
def foo[F[_]: EitherT[_, String, Int]] = ???
or *
instead of the last instance of _
. To be completely frank, the current situation is very confusing with the migration between the different placeholder syntaxes.
1 Like
G
is not bound in the example. What’s its signature? EDIT: Sorry, I misread. It is hard to read for sure.
1 Like
I guess that means it’s not currently on the roadmap. Would this be a candidate for a SIP?
It can be proposed as a SIP. I am not sure it will fly though. My gut reaction would be that types like this are too complicated, and a complicated notation is a healthy pushback against going further down that road. I want to re-orient Scala with a radical focus on simplicity and that holds for the language as well as the libraries.
1 Like
One alternative here is to use a type alias that returns a type lambda, this works:
type EitherTC[A, B] = [F[_]] =>> EitherT[F, A, B]
def foo[F[_]: EitherTC[String, Int]] = ???
This can be generalized to arbitrary constructors of the same arity, but this might be getting too weird:
type TC[M[_[_], _, _]] = [A, B] =>> [F[_]] =>> M[F, A, B]
def foo[F[_]: TC[EitherT][String, Int]] = ???
Yeah, I explicitly wanted to be able to skip naming these
So, the plan of record is to eventually allow _
to be used in types to construct type lambda as described in Wildcard Arguments in Types (disregard the version numbers used in this document, they were only meant to give a vague idea of the timeline and need to be updated), I think it’d make sense for it to also work with higher-kinded arguments.
The trouble is that as long as people cross-compile with Scala 2, it’s hard to repurpose _
. To help with this, I recently added support for ?
in both 2.13 and 2.12 (To aid cross building, allow `?` as a wildcard even without `-Xsource:3` by smarter · Pull Request #9990 · scala/scala · GitHub), but it will take a while before this becomes widespread. Meanwhile, it could make sense to implement the new meaning of _
under -source future
. The current implementation of -Ykind-projector
could serve as a basis for this, but it will need much more work.
1 Like