В конечном счете, я хочу предоставить одну реализацию класса типов для некоторого определенного типа T
и другую реализацию для всех других типов, которые не T
. Я подумал (возможно, неправильно), что самый простой способ сделать это - попробовать отрицание типов с помощью неоднозначных следствий, как описано в этом вопросе . Однако, если я случайно опущу неявное объявление класса типов, мой код все равно будет компилироваться (не так ли?), Но будет содержать ошибки, поскольку используется только одна из реализаций.
Вот как определяется граница контекста:
scala> trait NotAnInt[A]
defined trait NotAnInt
scala> implicit def everythingIsNotAnInt[A]: NotAnInt[A] = new NotAnInt[A] {}
everythingIsNotAnInt: [A]=> NotAnInt[A]
scala> implicit def intsAreInts1: NotAnInt[Int] = ???
intsAreInts1: NotAnInt[Int]
scala> implicit def intsAreInts2: NotAnInt[Int] = ???
intsAreInts2: NotAnInt[Int]
scala> implicit def nothingsAreInts1: NotAnInt[Nothing] = ???
nothingsAreInts1: NotAnInt[Nothing]
scala> implicit def nothingsAreInts2: NotAnInt[Nothing] = ???
nothingsAreInts2: NotAnInt[Nothing]
В этот момент NotAnInt [T] вызывается для всех T, кроме Int / Nothing:
scala> implicitly[NotAnInt[String]]
res3: NotAnInt[String] = $anon$1@1a24fe09
scala> implicitly[NotAnInt[Int]]
<console>:16: error: ambiguous implicit values:
both method intsAreInts1 of type => NotAnInt[Int]
and method intsAreInts2 of type => NotAnInt[Int]
match expected type NotAnInt[Int]
implicitly[NotAnInt[Int]]
^
scala> implicitly[NotAnInt[Nothing]]
<console>:18: error: ambiguous implicit values:
both method nothingsAreInts1 of type => NotAnInt[Nothing]
and method nothingsAreInts2 of type => NotAnInt[Nothing]
match expected type NotAnInt[Nothing]
implicitly[NotAnInt[Nothing]]
^
Теперь у меня определена моя граница контекста NotAnInt
, я могу создать свой класс типовс его реализациями:
scala> trait IntChecker[A] { def isInt(): Boolean }
defined trait IntChecker
scala> implicit val intIntChecker: IntChecker[Int] = new IntChecker[Int] { override def isInt = true }
intIntChecker: IntChecker[Int] = $anon$1@585dd35c
scala> implicit def otherIntChecker[A: NotAnInt]: IntChecker[A] = new IntChecker[A] { override def isInt = false }
otherIntChecker: [A](implicit evidence$1: NotAnInt[A])IntChecker[A]
Этот класс типов может использоваться как ожидалось:
scala> def printIntStatus[T: IntChecker](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatus: [T](t: T)(implicit evidence$1: IntChecker[T])Unit
scala> printIntStatus(3)
true
scala> printIntStatus("three")
false
Однако, следующее также компилируется:
scala> def printIntStatusWithBug[T](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatusWithBug: [T](t: T)Unit
scala> printIntStatusWithBug(3)
false
scala> printIntStatusWithBug("three")
false
Я бы не сталожидайте, что эта вторая функция будет скомпилирована, так как не должно быть никаких неявных IntChecker[T]
доступных. Я ожидаю, что everythingIsNotAnInt
является причиной этой проблемы, но я не могу придумать, как обойти это.
Меня интересует, почему этот подход терпит неудачу, а также альтернативные методы достижения той же цели. ,Спасибо.