🎓 A1Learner
🔍
0 of 45 lessons completed

Given Priority

Given priority is the rule that picks one given when two givens could fit a call. A specific instance wins over a general instance.

The specific instance wins for Int

Formatters holds a specific Formatter for Int and a general Formatter in a parent trait. Summon for Int picks the specific one.

trait Formatter[T]:
  def format(x: T): String
trait LowPriority:
  given [T]: Formatter[T] with
    def format(x: T): String = "any:" + x.toString
object Formatters extends LowPriority:
  given Formatter[Int] with
    def format(x: Int): String = "int:" + x.toString

@main def main(): Unit =
  import Formatters.given
  println(summon[Formatter[Int]].format(7))

A type with no specific instance uses the general one

String has no specific Formatter. Summon for String falls back to the general instance.

trait Formatter[T]:
  def format(x: T): String
trait LowPriority:
  given [T]: Formatter[T] with
    def format(x: T): String = "any:" + x.toString
object Formatters extends LowPriority:
  given Formatter[Int] with
    def format(x: Int): String = "int:" + x.toString

@main def main(): Unit =
  import Formatters.given
  println(summon[Formatter[String]].format("hi"))

The general instance also covers Double

Double also has no specific Formatter. The general instance formats it the same way.

trait Formatter[T]:
  def format(x: T): String
trait LowPriority:
  given [T]: Formatter[T] with
    def format(x: T): String = "any:" + x.toString
object Formatters extends LowPriority:
  given Formatter[Int] with
    def format(x: Int): String = "int:" + x.toString

@main def main(): Unit =
  import Formatters.given
  println(summon[Formatter[Double]].format(2.5))

Example

trait Formatter[T]:
  def format(x: T): String
trait LowPriority:
  given [T]: Formatter[T] with
    def format(x: T): String = "any:" + x.toString
object Formatters extends LowPriority:
  given Formatter[Int] with
    def format(x: Int): String = "int:" + x.toString

@main def main(): Unit =
  import Formatters.given
  println(summon[Formatter[Int]].format(7))
  println(summon[Formatter[String]].format("hi"))
  println(summon[Formatter[Double]].format(2.5))

Key points

  • Specific instance: an instance written for one exact type, such as Int.
  • General instance: an instance written for any type, using a type parameter.
  • Low-priority trait: a parent trait that holds the general instance.
  • Specific wins: when both instances fit, the compiler picks the specific one.
  • General fallback: a type with no specific instance still gets the general instance.

In this example, the trait describes a Formatter. The parent trait holds the general instance. The object holds the specific instance for Int. The import brings both instances into scope. The three prints show the specific format for Int and the general format for a word and a number.

Note

without the low-priority trait, two fitting givens would clash instead of ranking.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Scastie

Exercise

Formatters has a specific Formatter for Int and a general Formatter in a low-priority trait. Which instance does summon for Int pick?