Skip to content

Instantly share code, notes, and snippets.

@manjuraj
Last active August 29, 2015 14:06
Show Gist options
  • Save manjuraj/8e8383f90aac3c4e77f3 to your computer and use it in GitHub Desktop.
Save manjuraj/8e8383f90aac3c4e77f3 to your computer and use it in GitHub Desktop.
Typeclass example
//
// Show typeclass parameterized on a concrete type
//
trait Show[A] {
def show(a: A): String
}
object Show {
implicit object StringShow extends Show[String] {
def show(s: String) = s"*$s*"
}
implicit object IntShow extends Show[Int] {
def show(i: Int) = s"~$i~"
}
implicit def tupleShow[A : Show, B : Show] = new Show[(A, B)] {
def show(t: (A, B)) = {
val (a, b) = t
s"(${a.show}, ${b.show})"
}
}
implicit def setShow[A : Show] = new Show[Set[A]] {
def show(xs: Set[A]) = xs.map(_.show).mkString("(", ", ", ")")
}
implicit def mapShow[K : Show, V : Show] = new Show[Map[K, V]] {
def show(m: Map[K, V]) = m.map { case (k, v) => s"${k.show} -> ${v.show}" }.mkString("{", ", ", "}")
}
implicit class ShowPimps[A](a: A)(implicit ev: Show[A]) {
def show = ev.show(a)
}
// Alternatively, you can use a functional style:
//
// def show[A](a: A)(implicit ev: Show[A]) = ev.show(a)
// or
// def show[A : Show](a: A) = implicitly[Show[A]].show(a)
//
}
scala> import Show._
import Show._
scala> Set(1, 2, 3).show
res2: String = (~1~, ~2~, ~3~)
scala> Map(1 -> 2, 3 -> 4).show
res3: String = {~1~ -> ~2~, ~3~ -> ~4~}
scala> Map("hello" -> "world").show
res5: String = {*hello* -> *world*}
scala> Map(1 -> 2, "hello" -> "world").show
<console>:23: error: could not find implicit value for parameter ev: Show[scala.collection.immutable.Map[Any,Any]]
Map(1 -> 2, "hello" -> "world").show
^
<console>:23: error: value show is not a member of scala.collection.immutable.Map[Any,Any]
Map(1 -> 2, "hello" -> "world").show
^
trait Monoid[A] {
def zero: A
def op(l: A, r: A): A
}
//
// Foldable typeclass parameterized by a type constructor
//
trait Foldable[F[_]] {
def foldLeft[A, B](fa: F[A], z: => B)(f: (B, A) => B): B
def foldMap[A, B](fa: F[A])(f: A => B)(implicit M: Monoid[B]): B
}
object Foldable {
// List is Foldable
implicit object ListFoldable extends Foldable[List] {
def foldLeft[A, B](xs: List[A], z: => B)(f: (B, A) => B): B = xs.foldLeft(z)(f)
def foldMap[A, B](xs: List[A])(f: A => B)(implicit M: Monoid[B]): B = {
xs.map(f).foldLeft(M.zero)(M.op)
// or, xs.foldLeft(M.zero) { (a, e) => M.op(a, f(e)) }
}
}
implicit def foldableShow[F[_] : Foldable, A : Show] = new Show[F[A]] {
import Show._
def show(fa: F[A]): String = fa.foldLeft("") { case (s, a) => s"$s, ${a.show}" }
}
implicit class FoldablePimps[F[_], A](fa: F[A])(implicit ev: Foldable[F]) {
def foldLeft[B](z: => B)(f: (B, A) => B): B = ev.foldLeft(fa, z)(f)
}
}
scala> import Show._, Foldable._
import Show._
import Foldable._
scala> List(1, 2, 3).show
res7: String = , ~1~, ~2~, ~3~
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment