Polymorphic method works with type lambda, but not with type wildcard in Scala 3
Asked Answered
A

1

2

In Scala 3 I can define a functor for state using type lambda:

  given stateFunctor[S]: Functor[[A] =>> State[S, A]] with
    override def map[A, B](a: State[S, A])(fx: A => B): State[S, B] = State(a.run.andThen { case (s, a) => (s, fx(a)) })

I would expect it to work with ? or _ wildcard:

  given stateFunctor[S]: Functor[State[S, ?]] with
    override def map[A, B](a: State[S, A])(fx: A => B): State[S, B] = State(a.run.andThen { case (s, a) => (s, fx(a)) })

but I'm getting the following compilation error:

Type argument domain.State[S, ? <: AnyKind] does not have the same kind as its bound [_$1] given stateFunctor[S]: Functor[State[S, ? <: AnyKind]] with

Why doesn't it work? What am I missing? I thought Scala 3 supports kind-projector syntax for type wildcards.

Scala version: 3.1.3

If you need it, here are State and Functor definitions:

case class State[S, A](run:S => (S, A)):
  def exec(s:S):S = run(s)._1
  def eval(s:S):A = run(s)._2
trait Functor[F[_]]:
  def map[A, B](a: F[A])(fx: A => B): F[B]
Alina answered 31/10, 2022 at 18:21 Comment(3)
I believe you need a compiler flag.Wolff
@LuisMiguelMejíaSuárez sorry, witch one are you referring to? I thought -Ykind-projector is used only when using kind-projector (so basically in Scala 2)Alina
I've tried adding it using Global / scalacOptions += "-Ykind-projector" in build.sbt, but it didn't workAlina
L
5

? is wrong. ? is for existential type State[S, ?] (in Scala 2 it was State[S, _] aka State[S, A] forSome { type A }), not for type lambda.

_ is for type lambda (in Scala 2 they were emulated ({ type F[A] = State[S, A] })#F). So it should be State[S, _] but this is not implemented yet.

https://docs.scala-lang.org/scala3/reference/changed-features/wildcards.html

The syntax of wildcard arguments in types has changed from _ to ?

We would like to use the underscore syntax _ to stand for an anonymous type parameter, aligning it with its meaning in value parameter lists. So, just as f(_) is a shorthand for the lambda x => f(x), in the future C[_] will be a shorthand for the type lambda [X] =>> C[X].

So far you can write [A] =>> State[S, A] or use kind projector State[S, *]

scalaVersion := "3.2.1"

scalacOptions += "-Ykind-projector"
Loveless answered 1/11, 2022 at 2:53 Comment(3)
These next few years in Scala are going to be so ugly, when it comes to type projections. The transition plan for what ?, _, and * mean in types is just plain confusing, and until all of the future changes have been implemented fully, it's going to be a mess.Renner
Ahh, you're right! I've read that and missed the part that it's going to be implemented, I thought it's already available. Apparently I cannot read... Thank you, Dmytro!Alina
@SilvioMayolo Not necessarily so big mess if people use Scalafix rules.Loveless

© 2022 - 2024 — McMap. All rights reserved.