Skip to content

Instantly share code, notes, and snippets.

View deanwampler's full-sized avatar

Dean Wampler deanwampler

View GitHub Profile
@deanwampler
deanwampler / scala2-3-Conversion-old.scala
Created October 18, 2020 16:11
Using the old mechanism of an implicit conversion method
implicit def toDollars(d: Double): Dollars = Dollars(d)
@deanwampler
deanwampler / scala2-3-Conversion2.scala
Last active December 27, 2020 15:22
Implementing `apply` explicitly in a Conversion.
given Conversion[Double,Dollars] with
def apply(d: Double): Dollars = Dollars(d)
@deanwampler
deanwampler / scala2-3-MonoidTypeClassDef.scala
Last active December 27, 2020 15:28
Example of Scala 3 syntax for type classes
// Adapted from this Dotty documentation:
// https://dotty.epfl.ch/docs/reference/contextual/type-classes.html
trait Semigroup[T]:
extension (t: T)
def combine(other: T): T
def <+>(other: T): T = t.combine(other)
trait Monoid[T] extends Semigroup[T]:
def unit: T
given StringMonoid: Monoid[String] with
def unit: String = ""
extension (s: String) def combine(other: String): String = s + other
given IntMonoid: Monoid[Int] with
def unit: Int = 0
extension (i: Int) def combine(other: Int): Int = i + other
"2" <+> ("3" <+> "4") // "234"
("2" <+> "3") <+> "4" // "234"
StringMonoid.unit <+> "2" // "2"
"2" <+> StringMonoid.unit // "2"
2 <+> (3 <+> 4) // 9
(2 <+> 3) <+> 4 // 9
IntMonoid.unit <+> 2 // 2
2 <+> IntMonoid.unit // 2
given NumericMonoid[T](using num: Numeric[T]): Monoid[T] with
def unit: T = num.zero
extension (t: T) def combine(other: T): T = num.plus(t, other)
2.2 <+> (3.3 <+> 4.4) // 9.9
(2.2 <+> 3.3) <+> 4.4 // 9.9
BigDecimal(3.14) <+> NumericMonoid.unit
NumericMonoid[BigDecimal].unit <+> BigDecimal(3.14)
case class SortableSeq[A](seq: Seq[A]):
// Transform converts an A to B so you can order using the Bs, but a sequence of As is returned.
// The first two methods show the familiar Scala 2 syntax, which can still be used in 3.0
def sortByImplicits2[B](transform: A => B)(implicit o: Ordering[B]): SortableSeq[A] =
new SortableSeq(seq.sortBy(transform)(o))
def sortByImplicits2[B : Ordering](transform: A => B): SortableSeq[A] =
new SortableSeq(seq.sortBy(transform)(implicitly[Ordering[B]]))
// New Scala 3 using clauses. Note that we use 'using' when passing values explicitly:
def sortBy1a[B](transform: A => B)(using o: Ordering[B]): SortableSeq[A] =
given evenOdd: Ordering[Int] = new Ordering[Int]:
def compare(i: Int, j: Int): Int = i%2 compare j%2 match
case 0 => i compare j
case c => -c
// Equivalent to the following form:
// given evenOdd2: Ordering[Int] with
// def compare(i: Int, j: Int): Int = i%2 compare j%2 match
// case 0 => i compare j
// case c => -c
// Variation of https://gist.github.com/deanwampler/e806a3301380d5d70c3247264afb076a
trait Semigroup[T]:
extension (t: T)
infix def combine(other: T): T // infix allows "foo combine bar".
def <+>(other: T): T = t.combine(other)
trait Monoid[T] extends Semigroup[T]:
def unit: T
object O1:
val name = "O1"
def m(s: String) = s"$s, hello from $name"
class C1
class C2
given c1: C1 = new C1 // The type annotation ": C1" is required for givens.
given c2: C2 = new C2 // same.
// Scala 2 uses _ as the wild card instead of *. You can still use _ in 3.0.
import O1.* // Import everything EXCEPT the givens, c1 and c2