The following is a simplified version of a type-mismatch error I'm trying to solve:
trait Foo[A] {
type B
val b: B
}
trait Bar[T, R[_]] {
val r: R[T]
}
object TypeMismatch extends App {
def baz[T, U](bar: Bar[T, Foo { type B = U }]): Foo[T] { type B = U } = {
bar.r
}
}
The above code produces the following error:
Foo.scala:12: error: type mismatch;
found : Foo[T]{type B = U}
required: Foo[T]{type B = U}
bar.r
^
Any insight regarding how Scala determines the types are mismatched?
Foo { type B = U }
is incorrect. You're trying to add type refinement to type constructor while you mean adding type refinement to a proper type and considering corresponding type lambda.
Try ({type λ[a] = Foo[a] { type B = U }})#λ
def baz[T, U](bar: Bar[T, ({type λ[a] = Foo[a] { type B = U }})#λ]): Foo[T] { type B = U } = {
bar.r
}
https://scastie.scala-lang.org/h8lYBBlpS2WdPVTxKF5JMQ
With kind-projector this should be λ[a => Foo[a] { type B = U }]
https://scastie.scala-lang.org/DmytroMitin/I0m86QshRe2k9vee0XPNTw
In Scala 3 [a] =>> Foo[a] { type B = U }
https://scastie.scala-lang.org/aYEEeIm4RgKgDHNwYNeVkA
It's better to introduce Aux
-type
trait Foo[A] {
type B
val b: B
}
object Foo {
type Aux[A, B0] = Foo[A] { type B = B0 }
}
and then write Foo.Aux[*, U]
with kind-projector