Sto usando scala 2.10.0-snapshot datato (20.120.522) e hanno i seguenti file Scala:Risoluzione implicita in scala 2.10.x. cosa sta succedendo?
questo definisce il typeclass e un'istanza typeclass base:
package com.netgents.typeclass.hole
case class Rabbit
trait Hole[A] {
def findHole(x: A): String
}
object Hole {
def apply[A: Hole] = implicitly[Hole[A]]
implicit val rabbitHoleInHole = new Hole[Rabbit] {
def findHole(x: Rabbit) = "Rabbit found the hole in Hole companion object"
}
}
questo è l'oggetto del pacchetto:
package com.netgents.typeclass
package object hole {
def findHole[A: Hole](x: A) = Hole[A].findHole(x)
implicit val rabbitHoleInHolePackage = new Hole[Rabbit] {
def findHole(x: Rabbit) = "Rabbit found the hole in Hole package object"
}
}
e qui è la prova:
package com.netgents.typeclass.hole
object Test extends App {
implicit val rabbitHoleInOuterTest = new Hole[Rabbit] {
def findHole(x: Rabbit) = "Rabbit found the hole in outer Test object"
}
{
implicit val rabbitHoleInInnerTest = new Hole[Rabbit] {
def findHole(x: Rabbit) = "Rabbit found the hole in inner Test object"
}
println(findHole(Rabbit()))
}
}
Come potete vedere, Hole
è un semplice typeclass che definisce un metodo che un Rabbit
sta cercando di trovare. Sto cercando di capire le implicite regole di risoluzione su di esso.
con tutti e quattro i casi typeclass non commentate, scalac lamenta ambiguità su
rabbitHoleInHolePackage
erabbitHoleInHole
. (Perché?)se commento fuori
rabbitHoleInHole
, scalac compila e torno "Coniglio ha trovato il foro nell'oggetto pacchetto Foro". (Non dovrebbe impliciti in ambito locale hanno la precedenza?)Se dunque io commento fuori
rabbitHoleInHolePackage
, scalac lamenta ambiguità surabbitHoleInOuterTest
erabbitHoleInInnerTest
. (Perché? Nell'articolo di eed3si9n, URL di seguito, ha trovato impliciti btw interni ed esterni portata possono avere la precedenza diverso.)Se dunque io commento fuori
rabbitHoleInInnerTest
, scalac compila e torno "Rabbit trovato il buco nell'oggetto Test esterno ".
Come si può vedere, i comportamenti di cui sopra non seguono affatto le regole che ho letto sulla risoluzione implicita. Ho descritto solo una minima parte delle combinazioni che puoi fare per commentare/escludere le istanze e la maggior parte di esse sono davvero molto strane - e non ho ancora ottenuto importazioni e sottoclassi.
Ho letto e guardato presentation by suereth, stackoverflow answer by sobral e a very elaborate revisit by eed3si9n, ma sono ancora completamente sconcertato.
Hai provato con 2.9.x? –
i comportamenti sono diversi rispetto a 2.9.2 * con tutti e quattro i casi typeclass commentata, scalac compila e torno "Rabbit trovato il buco nel oggetto di prova interno" * se ho commentato rabbitHoleInHole, scalac compila e ottengo indietro "Coniglio ha trovato il buco nell'oggetto Test interno". * se poi ho commentato rabbitHoleInHolePackage, scalac compila e torno "Rabbit ha trovato il buco nell'oggetto Test interno". * se poi ho commentato rabbitHoleInInnerTest, scalac compila e torno "Rabbit ha trovato il buco nell'oggetto Test esterno". –
C'era un bug nelle regole di inferenza con Scala fino a 2.9, che è stato scoperto da qualcuno qui su Stack Overflow che ha cercato di capire come le specifiche dettavano il comportamento che stava vedendo. –