Skip to content

Instantly share code, notes, and snippets.

@sideeffffect
Created August 14, 2019 07:13
Show Gist options
  • Save sideeffffect/bbfeda29057ad707bf8382e9b999572d to your computer and use it in GitHub Desktop.
Save sideeffffect/bbfeda29057ad707bf8382e9b999572d to your computer and use it in GitHub Desktop.
Scala Type Classes
package com.avast.scalamodulesexperiment
object Polymorphism {
trait Animal {
def makeSound: String
}
class Dog extends Animal {
override def makeSound: String = "haf"
}
class Cat extends Animal {
override def makeSound: String = "mnau"
}
def play(animal: Animal): String = {
"my animal make sound " + animal.makeSound
}
sealed trait List[A]
case class Empty[A]() extends List[A]
case class Cons[A](head: A, tail: List[A]) extends List[A]
def length[A](list: List[A]): Int =
list match {
case Empty() => 0
case Cons(_, tail) => 1 + length(tail)
}
def second[A, B](a: A, b: B): B = b
val person = new {
val fn = "John"
val ln = "Smith"
val num = 123
}
def hello(p: {
val fn: String
val num: String
}): String = {
"hello " + p.fn + " " + p.num + "!"
}
def plus(a: Int, b: Int): String =
(a + b).toString
def plus(a: Double, b: Double): Double =
a + b
def plus(a: String, b: String): String =
"hello " + a + " " + b
}
object tcExplicit {
sealed trait List[A]
case class Empty[A]() extends List[A]
case class Cons[A](head: A, tail: List[A]) extends List[A]
case class Person(name: String, age: Int)
trait Eq[A] {
def equal(x: A, y: A): Boolean
}
object EqPerson extends Eq[Person] {
override def equal(x: Person, y: Person): Boolean =
???
}
def ifSame[A, B, C](x: A, y: A, b: B, c: C)(EqA: Eq[A]): Either[B, C] =
if (EqA.equal(x, y)) {
Left(b)
} else {
Right(c)
}
val p1: Person = ???
val p2: Person = ???
ifSame(p1, p2, 42, "asdf")(EqPerson)
def EqList[A](EqA: Eq[A]): Eq[List[A]] = new Eq[List[A]] {
override def equal(x: List[A], y: List[A]): Boolean = {
(x, y) match {
case (Empty(), Empty()) => true
case (Cons(h1, t1), Cons(h2, t2)) =>
if (EqA.equal(h1, h2))
equal(t1, t2)
else
false
case _ => false
}
}
}
val p3: Person = ???
ifSame(Cons(p1, Empty()), Cons(p2, Empty()), 42, "asdf")(EqList(EqPerson))
trait Comparator[A] extends Eq[A] {
def compare(x: A, y: A): Int
override def equal(x: A, y: A): Boolean = compare(x, y) == 1
}
object ComparatorPerson extends Comparator[Person] {
override def compare(x: Person, y: Person): Int =
x.name.compare(y.name) match {
case 0 => x.age.compare(y.age)
case i => i
}
}
ifSame(p1, p2, 42, "asdf")(ComparatorPerson)
trait Semigroup[A] {
def combine(x: A, y: A): A
}
trait Monoid[A] extends Semigroup[A] {
def empty: A
}
def accumulate[A](list: List[A])(Monoid: Monoid[A]): A =
list match {
case Empty() => Monoid.empty
case Cons(head, tail) =>
val accTail = accumulate(tail)(Monoid)
Monoid.combine(head, accTail)
}
}
object implicitMachinery {
case class Person(name: String, age: Int)
sealed trait List[A]
case class Empty[A]() extends List[A]
case class Cons[A](head: A, tail: List[A]) extends List[A]
trait Eq[A] {
def equal(x: A, y: A): Boolean
}
implicit object EqPerson extends Eq[Person] {
override def equal(x: Person, y: Person): Boolean = ???
}
implicit def EqList[A](implicit EqA: Eq[A]): Eq[List[A]] = new Eq[List[A]] {
override def equal(x: List[A], y: List[A]): Boolean = {
(x, y) match {
case (Empty(), Empty()) => true
case (Cons(h1, t1), Cons(h2, t2)) =>
if (EqA.equal(h1, h2))
equal(t1, t2)
else
false
case _ => false
}
}
}
def ifSame[A, B, C](x: A, y: A, b: B, c: C)(
implicit EqA: Eq[A]): Either[B, C] =
if (EqA.equal(x, y)) {
Left(b)
} else {
Right(c)
}
val p1: Person = ???
val p2: Person = ???
ifSame(Cons(p1, Empty()): List[Person], Cons(p2, Empty()), 42, "asdf")
}
object interfaces {
trait Equatable[A] {
def equal(other: A): Boolean
}
case class Human(name: String, age: Int) extends Equatable[Human] {
override def equal(other: Human): Boolean = ???
}
def ifSame2[A <: Equatable[A], B, C](x: A, y: A, b: B, c: C): Either[B, C] =
if (x.equal(y)) {
Left(b)
} else {
Right(c)
}
class List2[A <: Equatable[A]] extends Equatable[List2[A]] {
override def equal(other: List2[A]): Boolean = ???
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment