A complete Dotty (Scala 3) “given” example

I’ll write more about Scala/Dotty givens in future blog posts, but for today, here’s a complete Dotty given/using example, which compiles with Dotty 0.24 in May, 2020:

/**
  * source code from these two links, updated to the dotty 0.24
  * syntax in may, 2020:
  * https://dotty.epfl.ch/docs/reference/contextual/givens.html
  * https://stackoverflow.com/questions/59456843/how-to-use-given-in-dotty
  */
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 as Ord[Int]:
    def compare(x: Int, y: Int) =
        if (x < y) -1 else if (x > y) +1 else 0

given listOrd[T](using ord: Ord[T]) as 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)

def whichIsBigger[T](x: T, y: T)(using 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"

@main def main =
    println(whichIsBigger(2, 1))

As noted in the comments, the source code comes from the two links shown. All I did was update the whichIsBigger function to use using instead of given, and then I converted all of the code to use the Scala 3 (Dotty) significant indentation syntax, which I prefer.

Dotty extension methods

Also, if this code looks unusual:

def (x: T) > (y: T) = compare(x, y) > 0

It may help to know that it is a Dotty/Scala 3 extension method. It’s the Dotty way to declare that you’re adding > as a method to the T data type.

As a point of comparison, a few months ago I wrote this Dotty extension method:

def (s: String) makeInt(radix: Int): Int = Integer.parseInt(s, radix)

If you look at the two methods next to each other you’ll see that they are declared the same way:

def (x: T)      >      (y: T)            = compare(x, y) > 0
def (s: String) makeInt(radix: Int): Int = Integer.parseInt(s, radix)
def (a: A)      funName(b: B)      : C   = <function body, use a and b>

The biggest differences are:

  • The method name > compared to the name makeInt
  • The > method doesn’t have its return type declared

In summary, if you wanted to see a Dotty given/using example, along with a Dotty extension method, I hope this is helpful.