Skip to content

Commit

Permalink
Make Show contravariant without breaking things (#1649)
Browse files Browse the repository at this point in the history
  • Loading branch information
edmundnoble authored and kailuowang committed Jul 7, 2017
1 parent 8e8c654 commit cb84fd4
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
9 changes: 7 additions & 2 deletions core/src/main/scala/cats/Show.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ import cats.functor.Contravariant
* made a toString method, a Show instance will only exist if someone
* explicitly provided one.
*/
@typeclass trait Show[T] {
@typeclass trait Show[T] extends Show.ContravariantShow[T] {
// duplicated so simulacrum knows it requires an instance of this trait
def show(t: T): String
}

object Show {
trait ContravariantShow[-T] {
def show(t: T): String
}

/** creates an instance of [[Show]] using the provided function */
def show[A](f: A => String): Show[A] = new Show[A] {
def show(a: A): String = f(a)
Expand All @@ -27,7 +32,7 @@ object Show {

final case class Shown(override val toString: String) extends AnyVal
object Shown {
implicit def mat[A](x: A)(implicit z: Show[A]): Shown = Shown(z show x)
implicit def mat[A](x: A)(implicit z: ContravariantShow[A]): Shown = Shown(z show x)
}

final case class ShowInterpolator(_sc: StringContext) extends AnyVal {
Expand Down
19 changes: 12 additions & 7 deletions tests/src/test/scala/cats/tests/ShowTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,28 @@ class ShowTests extends CatsSuite {
checkAll("Contravariant[Show]", ContravariantTests[Show].contravariant[Int, Int, Int])
checkAll("Contravariant[Show]", SerializableTests.serializable(Contravariant[Show]))

sealed trait TimeOfDay
case object Morning extends TimeOfDay
object TimeOfDay {
implicit val showTimeOfDay: Show[TimeOfDay] = Show.show { case Morning => "morning" }
}

test("show string interpolator") {
case class Cat(name: String)
object Cat {
implicit val showCat: Show[Cat] = Show.show(_.name)
}

sealed trait TimeOfDay
case object Morning extends TimeOfDay
object TimeOfDay {
implicit val showTimeOfDay: Show[TimeOfDay] = Show.show { case Morning => "morning" }
}

val tod: TimeOfDay = Morning
val cat = Cat("Whiskers")

assertResult("Good morning, Whiskers!")(show"Good $tod, $cat!")

assertResult("Good morning, Whiskers!")(show"Good $tod, ${List(cat).head}!")
}

test("show string interpolator and contravariance") {
val tod: Morning.type = Morning

assertResult("Good morning")(show"Good $tod")
}
}

0 comments on commit cb84fd4

Please sign in to comment.