In scala, functions are covariant in their output type, and contravariant in their input type.
For example, if Dog
is a subtype of Animal
, then
T => Dog
is a subtype of T => Animal
, and
Animal => T
is a subtype of Dog => T
In other words, a producer of Dog
can go where a producer of Animal
is expected, and
a consumer of Animal
can go where a consumer of Dog
is expected.
So why do I get this compile error:
def useF(f: Nothing => Unit): Unit = ()
def f(x: Unit): Unit = ()
useF(f) // ok
useF(() => ()) // error
/*
example.scala:4: error: type mismatch;
found : () => Unit
required: Nothing => Unit
useF(() => ())
*/
I thought that Nothing
is a subtype of Unit
, so () => ()
should be a subtype of Nothing => ()
, since () => ()
is of type Unit => Unit
. What is the difference in type signature between f
and () => ()
?
Your logic is correct. Just syntax is wrong.
() => T
is not Function1[Unit, T]
. It is actually a syntax for lambda with no argument which results in Function0[T]
. The parenthesis here is not Unit. It's a syntax to denote zero arguments
The correct way to construct a Unit => Unit
is:
(_: Unit) => Unit
You can add explicit type annotation to verify:
val f: Function1[Unit, Unit] = _ => ()
useF(f)
// No error