Dato un typeclass dove la selezione istanza deve essere eseguito in base al tipo di ritorno:imprevisto risoluzione implicita sulla base di inferenza da tipo di ritorno
case class Monoid[A](m0: A) // We only care about the zero here
implicit def s[T] : Monoid[Set[T]] = Monoid(Set.empty[T])
implicit def l[T] : Monoid[List[T]] = Monoid(List.empty[T])
def mzero[A](implicit m: Monoid[A]) : A = m.m0
Perché Scala (2.11.6) non riescono a risolvere il corretto esempio:
scala> mzero : List[Int]
<console>:24: error: ambiguous implicit values:
both method s of type [T]=> Monoid[Set[T]]
and method l of type [T]=> Monoid[List[T]]
match expected type Monoid[A]
mzero : List[Int]
^
quando non ha problemi a trovare un implicito in base al tipo di ritorno quando si utilizza la funzione implicitamente (abbiamo ridefinire qui come i per illustrare come s analoghe sui è di mzero)
def i[A](implicit a : A) : A = a
scala> i : Monoid[List[Int]]
res18: Monoid[List[Int]] = Monoid(List())
Il Monoid[A]
, invece di Monoid[List[Int]]
nel messaggio di errore è sconcertante.
Suppongo che molti contributori scalaz abbiano familiarità con questo problema in quanto sembra limitare la praticità dei typeclass in scala.
EDIT: Sto cercando di ottenere questo funzionamento senza dedurre l'inferenza del tipo. Altrimenti mi piacerebbe capire perché non è possibile. Se questa limitazione è documentata come un problema di Scala, non potrei trovarlo.
I limiti della capacità di Scala di utilizzare i tipi di ritorno attesi per guidare l'inferenza dei parametri di tipo quando sono coinvolti impliciti sono incredibilmente confusi, quindi tutti scrivono semplicemente 'mzero [Elenco [Int]]'. –
Come soluzione, puoi scappare ridefinendo 'mzero' come' def mzero [A] (implicito m: Monoid [_ <: A]): A = m.m0'. Ut mi piacerebbe andare con 'mzero [List [Int]]' come menzionato da Travis Brown. –
Impressionante e sorprendente. Grazie! Alcuna spiegazione? Questo sembra rilassare il tipo e ottenere meno partite! –