Search code examples
scalasbtimplicitdottyscala-3

How to use given in Dotty?


I was looking at Dotty docs under Contextual Abstractions page and I saw the Given Instances.

Given instances (or, simply, "givens") define "canonical" values of certain types that serve for synthesizing arguments to given clauses. Example:

trait Ord[T] {
  def compare(x: T, y: T): Int
  def (x: T) < (y: T) = compare(x, y) < 0
  def (x: T) > (y: T) = compare(x, y) > 0
}

given intOrd: Ord[Int] {
  def compare(x: Int, y: Int) =
    if (x < y) -1 else if (x > y) +1 else 0
}

given listOrd[T]: (ord: Ord[T]) => Ord[List[T]] {

  def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match {
    case (Nil, Nil) => 0
    case (Nil, _) => -1
    case (_, Nil) => +1
    case (x :: xs1, y :: ys1) =>
      val fst = ord.compare(x, y)
      if (fst != 0) fst else compare(xs1, ys1)
  }
}

But this example from docs never explains how to use given. I pulled the test Dotty example project and try yo use it, but I don't quite understand it.

Is it a new keyword ? Do we import it ? Or am I missing something .


Solution

  • Here's an example of using the given instance. Let's say we want to compare two integers, and see which is bigger than the other. We can leverage the already defined intOrd above and write:

    def whichIsBigger[T](x: T, y: T)(given ord: Ord[T]): String = {
      ord.compare(x, y) match {
        case -1 => s"$x is less than $y"
        case 0 => s"$x and $y are equal"
        case 1 => s"$x is greater than $y"
      }
    }
    
    println(whichIsBigger(2, 1))
    

    Which yields:

    2 is greater than 1
    

    We were able to do this because there was a named given instance in scope, otherwise, the compiler would have complained it doesn't have an Ord[Int].

    Is it a new keyword ? Do we import it ? Or am I missing something.

    It is a new keyword, one which replaces a specific part of implicit definition in Scala 2. If this was Scala 2, we would have written:

    implicit val intOrd: Ord[Int] = new Ord[Int] {
      def compare(x: Int, y: Int) =
        if (x < y) -1 else if (x > y) 1 else 0
    }
    
    def whichIsBigger[T](x: T, y: T)(implicit ord: Ord[T]): String