Skip to content

Instantly share code, notes, and snippets.

@futtetennista
Created July 31, 2022 19:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save futtetennista/290613bf9eae5c8f8451e80371b23c99 to your computer and use it in GitHub Desktop.
Save futtetennista/290613bf9eae5c8f8451e80371b23c99 to your computer and use it in GitHub Desktop.
Type classes in Scala 3
trait Semigroup[T]:
def mappend(x: T, y: T): T
trait Monoid[T] extends Semigroup[T]:
def empty: T
object Semigroup:
given sumIntSemigroup: Semigroup[Int] with
override def mappend(x: Int, y: Int): Int = x + y
given prodIntSemigroup: Semigroup[Int] with
override def mappend(x: Int, y: Int): Int = x * y
given stringSemigroup: Semigroup[String] with
override def mappend(x: String, y: String): String =
x + y
import Semigroup.given
object Monoid:
given prodIntMonoid: Monoid[Int] with
override def mappend(x: Int, y: Int): Int =
prodIntSemigroup.mappend(x, y)
def empty = 1
given sumIntMonoid: Monoid[Int] with
override def mappend(x: Int, y: Int): Int =
sumIntSemigroup.mappend(x, y)
def empty = 0
given stringMonoid: Monoid[String] with
override def mappend(x: String, y: String) =
stringSemigroup.mappend(x, y)
override def empty = ""
end Monoid
import Monoid.given
// it doesn't compile
// (1:Int) mappend (2:Int)
sumIntMonoid.mappend(1, 2)
stringMonoid.mappend("1", "2")
case class SomeRecord(x: Int, y: String)
object SomeRecord:
val emptyRecord = SomeRecord(x = sumIntMonoid.empty, y = stringMonoid.empty)
given someRecordMonoid: Monoid[SomeRecord] with
override def mappend(self: SomeRecord, other: SomeRecord): SomeRecord =
SomeRecord(x = sumIntMonoid.mappend(self.x, other.x),
y = stringMonoid.mappend(self.y, other.y))
override def empty =
SomeRecord(x = sumIntMonoid.empty, y = stringMonoid.empty)
import SomeRecord.given
someRecordMonoid.mappend(SomeRecord(x = 1, y = "1"), SomeRecord(2, "2")) // mappend SomeRecord.empty
// SomeRecord(x = 1, y = "1") mappend SomeRecord(2, "2") mappend SomeRecord.emptyRecord
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment