Skip to content

Instantly share code, notes, and snippets.

@n4to4
Created September 30, 2016 04:07
Show Gist options
  • Select an option

  • Save n4to4/3ab11203f1730aab6975a2733d3e7aac to your computer and use it in GitHub Desktop.

Select an option

Save n4to4/3ab11203f1730aab6975a2733d3e7aac to your computer and use it in GitHub Desktop.
typeclass vs subtyping
// https://github.com/adelbertc/faq/blob/master/src/main/tut/typeclasses.compiled.md
object Main extends App {
def sumInts(list: List[Int]): Int = list.foldRight(0)(_ + _)
def concatStrings(list: List[String]): String = list.foldRight("")(_ ++ _)
def unionSets[A](list: List[Set[A]]): Set[A] = list.foldRight(Set.empty[A])(_ union _)
trait Monoid[A] {
def empty: A
def combine(x: A, y: A): A
}
object Monoid {
def apply[A: Monoid]: Monoid[A] = implicitly[Monoid[A]]
}
// subtyping
{
// final case class Pair[A <: Monoid[A], B <: Monoid[B]](first: A, second: B) extends Monoid[Pair[A, B]] {
// def empty: Pair[A, B] = ???
// def combine(x: Pair[A, B], y: Pair[A, B]): Pair[A, B] = ???
// }
// abstract case class Pair[A, B](first: A, second: B) extends Monoid[Pair[A, B]] {
// def empty(implicit eva: A <:< Monoid[A], evb: B <:< Monoid[B]): Pair[A, B] = ???
// def combine(x: Pair[A, B], y: Pair[A, B])(implicit eva: A <:< Monoid[A], evb: B <:< Monoid[B]): Pair[A, B] = ???
// }
def combineAll[A <: Monoid[A]](list: List[A]): A = ???
}
// typeclass
{
final case class Pair[A, B](first: A, second: B)
implicit val intMonoid = new Monoid[Int] {
def empty: Int = 0
def combine(x: Int, y: Int): Int = x + y
}
implicit val stringMonoid = new Monoid[String] {
def empty: String = ""
def combine(x: String, y: String): String = x + y
}
implicit def tuple2Instance[A, B](implicit A: Monoid[A], B: Monoid[B]): Monoid[Pair[A, B]] =
new Monoid[Pair[A, B]] {
def empty: Pair[A, B] = Pair(A.empty, B.empty)
def combine(x: Pair[A, B], y: Pair[A, B]): Pair[A, B] =
Pair(A.combine(x.first, y.first), B.combine(x.second, y.second))
}
// def combineAll[A](list: List[A])(implicit A: Monoid[A]): A =
// list.foldRight(A.empty)(A.combine)
def combineAll[A: Monoid](list: List[A]): A =
list.foldRight(Monoid[A].empty)(Monoid[A].combine)
assert { combineAll(List(Pair(1, 2), Pair(3, 4))) == Pair(4, 6) }
assert { combineAll(List(Pair("1", "2"), Pair("3", "4"))) == Pair("13", "24") }
assert { combineAll(List(Pair(1, "2"), Pair(3, "4"))) == Pair(4, "24") }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment