Inferindo o tipo de parâmetro implícito genérico do tipo de retorno
Digamos que eu tenha uma classe simples como esta
abstract class Foo {
implicit val impInt: Int = 42
def f[A]()(implicit a: A): A
val f2: Int = f()
}
Ao declarar valf2
, o compilador pode inferir que o tipo de parâmetro implícito da funçãof
éInt
porque esse tipo é igual ao tipo de resultado e o tipo de resultado precisa corresponder ao tipo de valorf2
, qual éInt
.
No entanto, jogando umOrdering[A]
na mistura:
def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()
resulta neste erro de compilação:
Valores implícitos ambíguos: o valor StringCanBuildFrom no objeto Predef do tipo => scala.collection.generic.CanBuildFrom [String, Char, String] e o método $ está em conformidade no objeto Predef do tipo [A] => <: <[A, A] corresponde ao tipo A esperado
Se eu adicionar as informações de tipo ao chamarf()
, compila:
val f2: Int = f[Int]()
Primeiro, encontrei o caso com pedidos implícitos e pensei que tivesse a ver com Scala deduzindo da esquerda para a direita; Eu pensei que não é capaz de corresponder ao tipo de retorno primeiro eentão inferir o tipo de parâmetro (implícito) def
. Mas então eu tentei o caso sem uma ordem implícita e vi que ele funciona - inferiu quef
deve ser parametrizado porInt
porque o tipo de retorno deve ser umInt
(Porquef2
é umInt
)
Observe que se removermosimplicit a: A
e deixe apenas o parâmetro implícito Ordering, o erro permanece, mas se torna
Expansão implícita divergente para o tipo Ordering [A] começando com o método Tuple9 no objeto Ordering.
Novamente, adicionando o parâmetro type para que ele se torneval f2: Int = f[Int]()
ajuda.
O que está acontecendo? Por que o compilador pode inferir esse parâmetroA
deve ser umInt
, mas não esse parâmetroOrdering[A]
deve ser umOrdering[Int]
?