-
-
Save propensive/8894fd2a58ac93bfa2c3 to your computer and use it in GitHub Desktop.
| // Define the following traits and companion object | |
| // It's in Rapture Core (https://github.com/propensive/rapture-core) if you don't want to | |
| trait LowPriorityDefaultsTo { implicit def fallback[T, S]: DefaultsTo[T, S] = null } | |
| object DefaultsTo extends LowPriorityDefaultsTo { implicit def defaultDefaultsTo[T]: DefaultsTo[T, T] = null } | |
| trait DefaultsTo[T, S] | |
| // Then, assuming we want to specify a default for a type class like `Namer`, | |
| case class Namer[T](name: String) | |
| // where we have a couple of alternatives, | |
| implicit val stringNamer = Namer[String]("string") | |
| implicit val intNamer = Namer[Int]("int") | |
| // we define the default one for a particular method like this: | |
| def myMethod[T](implicit default: T DefaultsTo String, namer: Namer[T]) = namer.name | |
| // Let's try it out in the REPL: | |
| scala> myMethod | |
| res0: String = string | |
| scala> myMethod[Int] | |
| res1: String = int |
Cool! :)
It's even more expectacular if you change it to case class Namer[T](t:T) , then you get type safety on the default value!
Jon, i wonder why did you place fallback to LowPriorityDefaultsTo, if i understand SLS correctly there's no ambiguity between these two implicits, since defaultDefaultsTo more specific then fallback, so if we omit the type parameter, the compiler would pick it instead of fallback, hence no ambiguity. So why placing it on a different layer?
To be sure this compiles on 2.11.7
trait DefaultsTo[Type, Default]
object DefaultsTo {
implicit def fallback[T, D]: DefaultsTo[T, D] = null
implicit def defaultDefaultsTo[T]: DefaultsTo[T, T] = null
}
trait Document
final class Table[DocType](val name: String)(implicit default: DocType DefaultsTo Document)
object Test {
val table = new Table("settings")
val table2 = new Table[String]("settings2")
}@4lex1v If that works, great! I tend to ignore the type-specificity rules and go straight with stacked traits, but that's a useful optimization!
For documentation purpose, the link to a similar implementation in the mongo scala driver: https://github.com/mongodb/mongo-scala-driver/blob/76dad47c8dbfc98b59867355a966cf95ef72e556/bson/src/main/scala/org/mongodb/scala/bson/DefaultHelper.scala
Very nice. I just added this to a much-used utility we have and it worked like a charm. Thanks!