How to trick Scala to not find duplicate implicits for Nothing

I am trying to use the typeclass pattern in Scala to mark all the valid API serializable types, so that we can have compile-time safety around what we serialize. Our underlying library accepts an AnyRef which can lead to weird errors when not explicitly declaring the type before serializing it.

We allow sending out a public model, an iterable of public models, an option of public model, or a unit.

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]

This method works well for everything except methods where the parameter type is an option. This is because None is an Option[Nothing], so T = Nothing which will tell the compiler to look up an implicit object of type SafeForPublic[Nothing] and it will find both SafeForPublic[PublicModel] as well as 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 ><

Any idea how I can trick the compiler to not find duplicate implicits for Nothing. I saw Miles Sabin had a trick using:

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 }
}

But I couldn't figure out how to use it. Halp?

Answers


Ok, thanks to some help from the Scala IRC channel, I figured out that LowPriority implicits was created to solve this issue.

I used this to fix it:

sealed class SafeForPublic[-T]
trait LowPriorityImplicits {
  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]
}
object Implicits extends LowPriorityImplicits {
  implicit object NothingOk extends SafeForPublic[Nothing]
}
import Implicits._
def boxed[T : SafeForPublic](t: Option[T]) = println("woohoo!")
boxed(None) // compiles! \o/

Need Your Help

Programmatically accessing an application through its UI

automation macros infopath

Earlier I asked a question about command-line parameters to automate processing of a file in InfoPath. I'll probably get the Tumbleweed badge for that one.

mysql query in php evaluates to true wrongly

php mysql

somewhere I'm doing something wrong, my query results to true instead of false. In my table the id 246 does exist but the lev is zero in the table. What am I doing wrong, this query should result...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.