Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Scala resolve generic types automatically?

Tags:

generics

scala

Please consider the following 2 lines of code:

def foo[F[B],A](fa: F[A]): String = fa.toString
println(foo(10))

It prints 10. What I wonder, is how it even compiles. I am trying to understand how Scala resolves the generics here. I mean, what are A, B, and F?

When looking at Intellij, it seems like 10 is converted from a Scala Int, to a Java Integer. But I don't know how the Java Integer is converted to any F[A] (Java Integer is not a generic type), as foo expects to receive.

like image 772
Tomer Shetah Avatar asked May 11 '26 07:05

Tomer Shetah


1 Answers

how the Java Integer is converted to any F[A](Java Integer is not generic type), as foo expects to receive.

Java Integer is subtype of Comparable[Integer]

public final class Integer extends Number implements Comparable<Integer>

Scala 2.13 infers F = Any and A = Nothing

scala> def foo[F[_],A](fa: F[A]) = fa
def foo[F[_], A](fa: F[A]): F[A]

scala> foo(10) // print
foo[Any, Nothing](10) // : Any
scala> foo(10)
val res9: Any = 10

This inference happens because of the presence of implicit conversion

implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer]

If we hide this conversion it will not compile

scala> implicit val int2Integer = null
val int2Integer: Null = null

scala> foo(10)
       ^
       error: no type parameters for method foo: (fa: F[A]): F[A] exist so that it can be applied to arguments (Int)
        --- because ---
       argument expression's type is not compatible with formal parameter type;
        found   : 10
        required: ?F[?A]
           ^
       error: type mismatch;
        found   : Int(10)
        required: F[A]

However note despite the fact that int2Integer made it compile, the implicit conversion did not actually take place (which might be a bug)

scala> foo(10)
val res9: Any = 10

where res9 should have been typed as Comparable[Integer] instead of Any.

Scala 3 (Dotty) infers F = Comparable and A = Integer as per -Xprint:typer

foo[Comparable, Integer](int2Integer(10))

and the implicit conversion is indeed applied

Starting dotty REPL...
scala> def foo[F[_],A](fa: F[A]) = fa
def foo[F[_$1], A](fa: F[A]): F[A]

scala> foo(10)
val res0: Comparable[Integer] = 10
like image 155
Mario Galic Avatar answered May 14 '26 10:05

Mario Galic



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!