Skip to content

Instantly share code, notes, and snippets.

@odersky
Last active February 18, 2022 13:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odersky/e08b8c2a665a0d2b77e6f2ecb07ff5f4 to your computer and use it in GitHub Desktop.
Save odersky/e08b8c2a665a0d2b77e6f2ecb07ff5f4 to your computer and use it in GitHub Desktop.
A Scala translation of James Ward's ContextReceivers example
// A literal Scala translation of James Ward's Context receivers example
// https://github.com/jamesward/oop-evolution/blob/context-receivers/gradleable/src/main/kotlin/adhocpoly/ContextReceivers.kt
// I had to rename `sum` to `summ` since `sum` already exists as a method on lists in Scala.
package adhocpoly
trait Summable[T]:
def tplus(t1: T, t2: T): T
object Summable:
def tplus[T](t1: T, t2: T)(using s: Summable[T]) = s.tplus(t1, t2)
extension [T: Summable](xs: Iterable[T])
def summ: T = xs.reduce(Summable.tplus)
@main def test =
given Summable[Char] with
def tplus(t1: Char, t2: Char): Char =
(t1 + t2 - ('a' - 1)).toChar
given Summable[String] with
def tplus(t1: String, t2: String): String =
t1.lazyZip(t2).map(Summable.tplus)
println(List('a', 'b').summ)
println(List("ah", "he").summ)
@odersky
Copy link
Author

odersky commented Feb 18, 2022

This was as close as possible to James Ward's version in https://github.com/jamesward/oop-evolution/blob/context-receivers/gradleable/src/main/kotlin/adhocpoly/ContextReceivers.kt.

A more idiomatic Scala version would use an infix method for the combine operation, like this:

package adhocpoly

trait Summable[T]:
  def tplus(t1: T, t2: T): T
  extension (t1: T) infix def combine (t2: T): T = tplus(t1, t2)

extension [T: Summable](xs: Iterable[T])
  def summ: T = xs.reduce(_ combine _)

@main def test =
  given Summable[Char] with
    def tplus(t1: Char, t2: Char): Char =
      (t1 + t2 - ('a' - 1)).toChar

  given Summable[String] with
    def tplus(t1: String, t2: String): String =
      t1.lazyZip(t2).map(_ combine _)

  println(List('a', 'b').summ)
  println(List("ah", "he").summ)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment