я мог бы использовать предложения отладки неявный:Scala: Как можно предотвратить импорт неявного значения?
Я хочу использовать неявный, x
:
type T
trait HasT {
implicit def x: T = ...
}
Но я также нужен импорт подстановочного из некоторого пакета foo
. Я пробовал два разных способа введения как:
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"
}
И потерпеть неудачу с «не может найти» (не «неоднозначные implicits значения»).
Это происходит, когда неявный идентификатор x: T
доступен в точке вызова метода через либо наследование, либо импорт.
Моим обходным путем является переинструкция x до неявного значения val перед импортом. Оба следующие работы:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
и
implicit val x2: T = x
import foo._
implicitly[T] // works!
Какое значение могло бы быть в обув, чтобы вызвать такое поведение?
Мое первое предположение состоит в том, что в foo
есть некоторая конкурирующая неявная, но если бы это был более высокий приоритет, то все еще работало бы следующее implicitly
, и если бы это было неоднозначное неявное, у меня возникла бы другая ошибка.
Второе предположение, предложенное милями сабином, - implicit shadowing. С тех пор я разъяснил свой пост, чтобы исключить эту возможность. Этот случай был бы совместим с моими ошибками, если бы я пробовал package hasT extends HasT; import hasT._
, но, как указывает som-snytt, эти два случая не приведут к затенению.
В моем конкретном случае это можно подтвердить, изменив имя неявного, которое я пытаюсь использовать.
(Возможно, я пропустил publishLocal
или reload
)
Теперь я на самом деле пытаюсь использовать пятно. Неявное T
выше на самом деле тип столбца отображения:
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
}
}
тип api
/foo
является JdbcProfile.API
. Оскорбительный неявный, вероятно, here, но я не могу сказать почему. Я попытаюсь заблокировать некоторые из них от импорта и посмотреть, могу ли я сузить его.
Ваш уменьшенный пример компилируется. Предполагается ли это? Я заметил, что вы не псевдоним 'T'' profile.api.BaseColu ... '. Наверное, это тоже не имеет значения. –
@ som-snytt Право! Он не будет компилироваться, если имплицитный был назван 'timeColumnType'. Майлз был прав, чтобы подозревать скрытое затенение. – stewSquared
Я начал называть мои implicits полным пути пакета по имени, чтобы избежать этого в будущем. – stewSquared