Skip to content

Instantly share code, notes, and snippets.

@tejancsu
Created May 30, 2017 04:10
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 tejancsu/f89cc5b70093a9dd518faedac67e450b to your computer and use it in GitHub Desktop.
Save tejancsu/f89cc5b70093a9dd518faedac67e450b to your computer and use it in GitHub Desktop.
case class MyShow[T](f: T => String) extends AnyVal
trait LowPriorityShow {
implicit def showAnything[T] = MyShow[T](_.toString)
}
object MyShow extends LowPriorityShow {
implicit val showDateTime = MyShow[DateTime](ISODateTimeFormat.dateTime().withZone(DateTimeZone.forID("America/New_York")).print _)
implicit def showOpt[T] = MyShow[Option[T]](_.fold("")(_.toString))
def show[T](v: T)(implicit s: MyShow[T]) = {
s.f(v)
}
}
println(MyShow.show(DateTime.now()))
//2017-05-30T00:08:22.851-04:00 -- This seems to pick the showDateTime implicit
println(MyShow.show(Some("abc"))) -- This picks showAnything instead of showOpt implicit
//Some(abc)
@ferranjr
Copy link

ferranjr commented Mar 20, 2018

Probably late to the party, but your issue here, is that the implicit resolution picks up the type Some[String] for the second case.

try this and you should be good for this case,
println(MyShow.show(Some("abc"): Option[String]))

in libraries like cats, you can see that there are some implicits to allow you to do "abc".some <- which defines the type result as Option[String] not leaving to the compiler to do type inference as it will result in Some[String]

alternatively, playing with variance should do the trick

import org.joda.time.{DateTime, DateTimeZone}
import org.joda.time.format.ISODateTimeFormat

trait Show[-T] {
  def show: T => String
}

trait LowPriorityShow {
  implicit def showAnything[T] = new Show[T] {
    def show: T => String = _.toString
  }
}

object Show extends LowPriorityShow {

  implicit val showString: Show[String] = new Show[String] {
    def show: String => String = identity
  }

  implicit val showDateTime: Show[DateTime] =
    new Show[DateTime] {
      def show: DateTime => String =
        ISODateTimeFormat.dateTime().withZone(DateTimeZone.forID("America/New_York")).print
    }

  implicit def showOpt[T : Show]: Show[Option[T]] =
    new Show[Option[T]] {
      def show: Option[T] => String = _.fold("")(implicitly[Show[T]].show)
    }

  def show[T : Show](v: T): String = implicitly[Show[T]].show(v)
}

println(Show.show(DateTime.now()))
println(Show.show(Some("abc")))
println(Show.show(12))

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