1

I have taken the following code almost entirely from the 'derive show' example found here: https://github.com/milessabin/kittens

import cats._, cats.derived._, cats.implicits._

object Test extends App {

  case class Address(street: String, city: String, state: String)

  case class ContactInfo(phoneNumber: String, address: Address)

  case class People(name: String, age: Double,  contactInfo: ContactInfo)

  val mike = People("Mike", 1.23,  ContactInfo("202-295-3928", Address("1 Main ST", "Chicago", "IL")))

  implicit val addressShow: Show[Address] = new Show[Address] {
    def show(a: Address) = s"${a.street}, ${a.city}, ${a.state}"
  }

//  I would like to use a custom version of Show for Doubles...
//  implicit val doubleShow: Show[Double] = new Show[Double] {
//    def show(d: Double) = s"Custom Double Show: $d"
//  }

  implicit val peopleShow: Show[People] = {
    import auto.show._
    semi.show
  }

  println(mike.show)

}

I would like to be able to use a custom version of Show[Double] (I don't really, but this is a nice minimal example which illustrate the problem I'm actually having)

If I un-comment my doubleShow I get the following error:

Error:(25, 10) ambiguous implicit values:
 both value emptyProductDerivedShow in trait MkShowDerivation of type => cats.derived.MkShow[shapeless.HNil]
 and method emptyCoproductDerivedShow in trait MkShowDerivation of type => cats.derived.MkShow[shapeless.CNil]
 match expected type cats.derived.MkShow[A]
    semi.show

How can I get this working? I would have expected my locally defined implicits to win out over any imported from cats...

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
user2682459
  • 999
  • 2
  • 13
  • 24

1 Answers1

2

Try implicit object instead of implicit val

implicit object doubleShow extends Show[Double] {
  def show(d: Double) = s"Custom Double Show: $d"
}

or use implicit val and change imports (don't import cats.instances.double._)

import cats._, cats.derived._
import cats.syntax.show._
import cats.instances.string._ // People uses String and Double

implicit val doubleShow: Show[Double] = new Show[Double] {
  def show(d: Double) = s"Custom Double Show: $d"
}
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Like the object way of doing this - I am curious as to why object works and val does not? – user2682459 May 29 '19 at 22:11
  • I have quickly found another example which doesn't work: new question https://stackoverflow.com/questions/56369317/kittens-ambiguous-imports-again – user2682459 May 29 '19 at 22:25
  • 1
    @user2682459 Type of `val doubleShow` is `Show[Double]` (the same as imported from cats), type of `object doubleShow` is `doubleShow.type` (tighter than imported from cats). More specific implicit wins. – Dmytro Mitin May 30 '19 at 05:50