mogę używać sugestie debugowania niejawna:Scala: W jaki sposób import może uniemożliwić znalezienie ukrytej wartości?
chcę używać niejawny, x
:
type T
trait HasT {
implicit def x: T = ...
}
Ale muszę również import wieloznaczny od jakiegoś pakietu foo
. Próbowałem dwa różne sposoby: wprowadzając zarówno
class UseT extends HasT {
import foo._
implicitly[T] // fails! "could not find implicit value"
// use foo stuff
}
class Use T {
object hasT extends HasT
import hasT.x
import foo._
implicitly[T] // fails! "could not find implicit value"
}
Zarówno powiedzie się z „nie można znaleźć” (nie „wartości niejednoznaczne implicits”).
Dzieje się tak, gdy niejawny identyfikator x: T
jest dostępny w punkcie wywołania metody przez dziedziczenie lub importowanie.
Moje obejście polega na ponownym powiązaniu x z niejawną wartością przed importem. Oba następujących prac:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
i
implicit val x2: T = x
import foo._
implicitly[T] // works!
Jaką wartość mogłaby być w foo spowoduje to zachowanie?
Moim pierwszym przypuszczeniem jest to, że niektóre konkurują domyślnie w foo
, ale jeśli był wyższy priorytet, następująca implicitly
nadal działałaby, a jeśli byłaby niejednoznaczna, otrzymywałbym inny inny błąd.
Drugie przypuszczenie, oferowane przez mile sabin, to implicit shadowing. Od tego czasu wyjaśniłem swój post, aby wykluczyć taką możliwość. Ten przypadek byłby zgodny z moimi błędami, gdybym próbował package hasT extends HasT; import hasT._
, ale jak zauważy som-snytt, te dwa przypadki nie spowodowałyby shadowingu.
W moim konkretnym przypadku można to potwierdzić, zmieniając nazwę niejawnego, którego próbuję użyć.
(Musiałem tęsknić za publishLocal
lub reload
)
Teraz rzeczywiście próbuję użyć śliskich. Domniemana T
wyżej faktycznie odwzorowanie typu kolumna
import slick.driver.JdbcProfile
class Custom { ... } // stored as `Long` in postgres
trait ColumnTypes {
val profile: JdbcProfile
import profile.api._ // this is `foo` above
type T = profile.BaseColumnType[Custom]
implicit def customColumnType: T =
MappedColumnType.base[Custom, Long](_.toLong, Custom.fromLong)
}
class DatabaseSchema(val profile: JdbcProfile) extends ColumnTypes {
// `implicitly[T]` does not fail here.
import profile.api._ // this is also `foo` above
// `implicitly[T]` fails here, but it's needed for the following:
class CustomTable(tag: Tag) extends Table[Custom](tag, "CUSTOMS") {
// following fails unless I rebind customColumnType to a local implicit
def custom = column[Custom]("CUSTOM")
def * = custom
}
}
Typ api
/foo
jest JdbcProfile.API
. Niewłaściwe naruszenie to prawdopodobnie here, ale nie mogę powiedzieć dlaczego. Spróbuję zablokować niektóre z nich przed importem i sprawdzić, czy mogę je zawęzić.
Twój zmniejszona przykład kompiluje. Czy powinno? Zauważam, że nie pseudo "T" do "profile.api.BaseColu ...". Prawdopodobnie to też nie powinno mieć znaczenia. –
@ som-snytt Right! Nie skompilowałoby się, gdyby niejawne miały nazwy 'timeColumnType'. Miles miał rację, podejrzewając ukryty cień. – stewSquared
Zacząłem nazywać moje implicity pełną ścieżką pakietu w nazwie, aby uniknąć tego w przyszłości. – stewSquared