Skip to content

Instantly share code, notes, and snippets.

@vitojeng
Last active January 12, 2018 06:50
Show Gist options
  • Save vitojeng/426c80bb725046d7160fe3a28a86d672 to your computer and use it in GitHub Desktop.
Save vitojeng/426c80bb725046d7160fe3a28a86d672 to your computer and use it in GitHub Desktop.
Type classes in Scala sample code

Sample code from Type classes in Scala

object TypeClasses0 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    val intCanShow: Show[Int] = new Show[Int] {
      def show(int: Int) = s"int $int"
    }
  }

  def main(args: Array[String]): Unit = {
    import Show._
    println( intCanShow.show(20) )
  }

}
object TypeClasses1 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    implicit val intCanShow: Show[Int] = new Show[Int] {
      def show(int: Int) = s"int $int"
    }

    // without context bound syntax
    def show1[A](a: A)(implicit sh: Show[A]) = sh.show(a)

    // context bound syntax
    def show2[A: Show](a: A) = implicitly[Show[A]].show(a)
  }


  def main(args: Array[String]): Unit = {
    import Show._
    println( show1(20) )
    println( show2(20) )
  }

}
object TypeClasses2 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    implicit val intCanShow: Show[Int] = new Show[Int] {
      def show(int: Int) = s"int $int"
    }

    def apply[A](implicit sh: Show[A]): Show[A] = sh

    def show[A:Show](a: A) = Show.apply[A].show(a)
    // def show[A:Show](a: A) = Show[A].show(a)
  }


  def main(args: Array[String]): Unit = {
    import Show._
    println( show(20) )
  }

}
object TypeClasses3 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    implicit val intCanShow: Show[Int] = new Show[Int] {
      def show(int: Int) = s"int $int"
    }

    def apply[A](implicit sh: Show[A]): Show[A] = sh

    def show[A:Show](a: A) = Show[A].show(a)
  }

  implicit class ShowOps[A](val a: A) {
    def show(implicit sh: Show[A]) = sh.show(a)
  }
  
//  implicit class ShowOps[A: Show](val a: A) {
//    def show = Show[A].show(a)
//  }  

  def main(args: Array[String]): Unit = {
    println( Show.show(20) )
    println( 40.show )
  }

}
object TypeClasses4 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    implicit val intCanShow: Show[Int] = new Show[Int] {
      def show(int: Int) = s"int $int"
    }

    // Add new type
    implicit val stringCanShow: Show[String] = new Show[String] {
      def show(str: String) =  s"string $str"
    }

    implicit class ShowOps[A: Show](val a: A) {
      def show = Show[A].show(a)
    }

    def apply[A](implicit sh: Show[A]): Show[A] = sh

    def show[A:Show](a: A) = Show[A].show(a)
  }

  def main(args: Array[String]): Unit = {
    import Show._
    println( show(20) )
    println( show("Hello") )

    println( 40.show )
    println( "Hello world".show )
  }

}
object TypeClasses5 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    private def instance[A](f: A => String): Show[A] = new Show[A] {
      def show(a: A): String = f(a)
    }

    implicit val intCanShow: Show[Int] = instance(int => s"int $int")
    implicit val stringCanShow: Show[String] = instance(str => s"string $str")

    implicit class ShowOps[A: Show](val a: A) {
      def show = Show[A].show(a)
    }

    def apply[A](implicit sh: Show[A]): Show[A] = sh

    def show[A:Show](a: A) = Show[A].show(a)
  }

  def main(args: Array[String]): Unit = {
    import Show._
    println( show(20) )
    println( show("Hello") )

    println( 40.show )
    println( "Hello world".show )
  }

}
object TypeClasses6 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    def instance[A](f: A => String): Show[A] = new Show[A] {
      def show(a: A): String = f(a)
    }

    implicit val intCanShow: Show[Int] = instance(int => s"int $int")
    implicit val stringCanShow: Show[String] = instance(str => s"string $str")

    def apply[A](implicit sh: Show[A]): Show[A] = sh

    object ops {
      implicit class ShowOps[A: Show](val a: A) {
        def show = Show[A].show(a)
      }
      def show[A:Show](a: A) = Show[A].show(a)
    }

  }

  def main(args: Array[String]): Unit = {
    import Show.ops._

    println( show(20) )
    println( show("Hello") )

    println( 40.show )
    println( "Hello world".show )
  }

}
object TypeClasses7 {

  trait Show[A] {
    def show(a: A): String
  }

  object Show {
    // use Single Abstract Method(SAM) types(Scala 2.12)
    implicit val intCanShow: Show[Int] = int => s"int $int"
    implicit val stringCanShow: Show[String] = str => s"string $str"

    def apply[A](implicit sh: Show[A]): Show[A] = sh

    object ops {
      implicit class ShowOps[A: Show](val a: A) {
        def show = Show[A].show(a)
      }
      def show[A:Show](a: A) = Show[A].show(a)
    }

  }

  // Extend own types
  case class Book(title: String, author: String)
  implicit val bookCanShow: Show[Book] = book => s"Title: ${book.title}, Author: ${book.author} "

  def main(args: Array[String]): Unit = {
    import Show.ops._

    println( show(20) )
    println( show("Hello") )

    println( 40.show )
    println( "Hello world".show )

    println( Book("Programming in Scala", "Martin Odersky").show )
  }

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment