Skip to content

Commit 32f3d5f

Browse files
authored
Merge pull request #6 from scalacenter/unreducible-application-hkt-wildcard
Add section about unreducible application of higher-kinded types to wildcard types
2 parents 19ed993 + 6535981 commit 32f3d5f

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

docs/cross-build.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,71 @@ implicit val locationWrites: Writes[Location] = (
5252
)(location => (location.lat, location.long)) // Compiles with both Scala 2 and Scala 3
5353
~~~
5454

55+
### Unreducible application of higher-kinded type to wildcard arguments
56+
57+
This error happens when you apply the “wildcard” type to a higher-kinded type.
58+
59+
Consider the following example:
60+
61+
~~~ scala
62+
trait Example {
63+
64+
type Foo[A]
65+
66+
def f(foo: Foo[_]): Unit // Error with Scala 3
67+
68+
def g(foos: Seq[Foo[_]]): Unit // Error with Scala 3
69+
70+
}
71+
~~~
72+
73+
It compiles with Scala 2, but Scala 3 produces the following errors:
74+
75+
~~~
76+
[error] -- [E043] Type Error:
77+
[error] 5 | def f(foo: Foo[_]): Unit // Warning with Scala 3
78+
[error] | ^^^^^^
79+
[error] |unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
80+
[error] -- [E043] Type Error:
81+
[error] 6 | def g(foos: Seq[Foo[_]]): Unit // Warning with Scala 3
82+
[error] | ^^^^^^
83+
[error] |unreducible application of higher-kinded type Example.this.Foo to wildcard arguments
84+
~~~
85+
86+
The reason for this error is that the type `Foo[_]` involves existential type quantification and this feature [has been removed from Scala 3](https://dotty.epfl.ch/docs/reference/dropped-features/existential-types.html).
87+
88+
Two solutions can be considered for cross-compiling.
89+
90+
In the case of the function `f`, we can change its signature to take a type parameter:
91+
92+
~~~ scala
93+
def f[A](foo: Foo[A]): Unit // Compiles with both Scala 2 and Scala 3
94+
~~~
95+
96+
The second function, `g`, requires more work. We want to accept collections containing
97+
values of type `Foo[A]` with possibly different types for the parameter `A`. To achieve
98+
this, we create a wrapper type that models the type parameter as a type member instead:
99+
100+
~~~ scala
101+
// Wrapper type
102+
trait SomeFoo {
103+
type T
104+
def value: Foo[T]
105+
}
106+
107+
// Construct a value of type `SomeFoo`
108+
def SomeFoo[A](foo: Foo[A]): SomeFoo =
109+
new SomeFoo {
110+
type T = A
111+
def value = foo
112+
}
113+
114+
def g(foos: Seq[SomeFoo]): Unit // Compiles with both Scala 2 and Scala 3
115+
~~~
116+
117+
Users will have to explicitly wrap their `Foo` values into `SomeFoo` by calling the
118+
corresponding constructor.
119+
55120
### Other incompatibilities
56121

57122
[Contributors Welcome!](CONTRIBUTING.md)

0 commit comments

Comments
 (0)