Я пытаюсь использовать шаблон typeclass в Scala, чтобы пометить все допустимые типы сериализуемых API, чтобы мы могли обеспечить безопасность во время компиляции вокруг того, что мы сериализуем. Наша базовая библиотека принимает AnyRef
, что может привести к странным ошибкам, когда явным образом не объявляю тип перед его сериализацией.Как обмануть Scala, чтобы не найти дублирующихся имплицитов для Nothing
Мы разрешаем отправку общедоступной модели, итерации общедоступных моделей, опции общедоступной модели или единицы.
trait PublicModel
case class UserModel(name: String) extends PublicModel
sealed class SafeForPublic[-T]
implicit object PublicModelOk extends SafeForPublic[PublicModel]
implicit object IterablePublicModelOk extends SafeForPublic[Iterable[PublicModel]]
implicit object OptionPublicModelOk extends SafeForPublic[Option[PublicModel]]
implicit object UnitOk extends SafeForPublic[Unit]
Этот метод работает хорошо для всех, кроме методов, в которых тип параметра является опцией. Это происходит потому, что None
является Option[Nothing]
, так T = Nothing
, который сообщит компилятору искать неявный объект типа SafeForPublic[Nothing]
и он найдет как SafeForPublic[PublicModel]
, а также SafeForPublic[Iterable[PublicModel]]
def boxed[T : SafeForPublic](t: Option[T]) = println("wooohoo!")
boxed(Some(None)) // works
boxed(Some(1)) // doesn't compile. Int is not a valid serializable model.
boxed(Some({})) // works
boxed(Some(UserModel("ok"))) // works
boxed(Some(Seq(UserModel("ok")))) // works
boxed(None) // doesn't compile, duplicate implicits ><
Любая идея, как я могу обмануть компилятор для не найти дубликаты неявки для Nothing
. Я видел, что у Майлза Сабина был трюк, используя:
sealed trait NotNothing[A]{
type B
}
object NotNothing {
implicit val nothing = new NotNothing[Nothing]{ type B = Any }
implicit def notNothing[A] = new NotNothing[A]{ type B = A }
}
Но я не мог понять, как его использовать. Halp?
Посмотрите на [этот вопрос] (http://stackoverflow.com/questions/15962743/using-context-bounds-negatively-to-ensure- type-class-instance-is-abs-from-s) для прохода трюка отрицания. Я закончил с родовым классом типа «Не [_]». См. Ответ для получения более подробной информации. – nadavwr