sealed trait Foo
case class Foo1() extends Foo
case class Foo2() extends Foo
case class Wrapper[A](a: A)
val x: Wrapper[Foo] = Wrapper(Foo2())
x match {
case w @ Wrapper(_: Foo1) =>
forFoo1(w.asInstanceOf[Wrapper[Foo1]])
case w @ Wrapper(_: Foo2) =>
forFoo2(w.asInstanceOf[Wrapper[Foo2]])
}
def forFoo1(foo1: Wrapper[Foo1]) = {
println("foo1)"sc
}
def forFoo2(foo2: Wrapper[Foo2]) = {
println("foo2")
}
On lines 11 and 13 the compiler already knows, that type of w is narrowed by pattern matching.
What you’re suggesting would be unsound in general, just because Wrapper(_: Foo1) matches doesn’t mean that the type argument of Wrapper is Foo1, it could either be a subtype or a supertype:
val x: Wrapper[Any] = Wrapper(Foo1())
val f = Foo1()
val y: Wrapper[f.type] = Wrapper(f)
Wrapper is invariant, so we can’t allow either x or y to be treated as subtypes of Wrapper[Foo1].
Rather than making inference go through heroic efforts, I think the real fix here is to make Ordering contravariant. This wasn’t something that would have worked in Scala 2 due to differences in implicit resolution, but it’d make sense now. Unfortunately, it’s not something we can do until we get to change the standard library in the distant future.
When using the underscore in function literals, the compiler can sometimes not infer the type. Example:
case class A(i: Int)
val o: Option[A] = Some(A(1))
val r1: Option[A] = o.flatMap(Option(_)) // works
val r2: Option[Int] = o.flatMap(Option(_.i)) // missing parameter type
Thanks for the clarification. I had a wrong mental model in mind. I wonder if the desugering rule could be extended to translate an _ into a function binding at the next “outer” level the needs a function valued parameter but is given a parameter of a different type.
That would be extremely confusing for anyone trying to read and understand the code, and it would break (possibly silently) based on small changes in APIs or type inference.
Inspired by a previous conversation here, I have a branch where the warning suggests the correct syntax. This is a common case because it’s a bit subtle. I’ll try to revive that PR.
enum CounterInput[Response]:
case Inc extends CounterInput[Unit]
case Dec extends CounterInput[Unit]
case Get extends CounterInput[Int]
val counterBehavior: [O] => (Int, CounterInput[O]) => (Int, O) =
[O] =>
(state: Int, msg: CounterInput[O]) =>
((state, msg) match
case (s, CounterInput.Inc) =>
(s + 1, ())
case (s, CounterInput.Dec) =>
(s + 1, ())
case (s, CounterInput.Get) =>
(s, s)
): (Int, O) // This is required due to another type inference bug? https://github.com/lampepfl/dotty/issues/15554
// fails to infer
val counterBehavior2: [O] => (Int, CounterInput[O]) => (Int, O) =
case (s, CounterInput.Inc) =>
(s + 1, ())
case (s, CounterInput.Dec) =>
(s + 1, ())
case (s, CounterInput.Get) =>
(s, s)
Last one gives
Missing parameter type
I could not infer the type of the parameter x$1 of expanded function:
x$1 =>
x$1 match
{
case (s, CounterInput.Inc) =>
(s + 1, ())
case (s, CounterInput.Dec) =>
(s + 1, ())
case (s, CounterInput.Get) =>
(s, s)
}.
val example: [T] => Int => Int = {case a: Int => a}
/*
Missing parameter type
I could not infer the type of the parameter x$1 of expanded function:
x$1 =>
x$1 match
{
case a:Int =>
a
}.
*/
Someone mentioned type inference along with eta expansion are not implemented in Dotty for polymorphic function types. I wonder if there are any plans for it. GADT kinda feels unergonomic without it.
Polymorphic eta-expansion is on it’s way !
I started work on it last semester: https://github.com/lampepfl/dotty/pull/14015
(as a semester project)
And one of the goals of my internship is to finish it, so unless something goes wrong, there will be a fully working version before the end of next semester !
(And it’ll get incorporated in the language maybe a little later)
Do note however this might not solve the problem discussed above, as in it’s simplest form, it will not add type lambdas to functions
def metafoo(f: [T] => T => T) = ???
metafoo(t => t) // will not compile with just Polymorphic Eta Exansion, it needs something more