Я взял следующий код почти полностью из примера 'derive show', найденного здесь: https://github.com/milessabin/котята
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)
}
Я хотел бы иметь возможность использовать пользовательскую версию Show[Double] (на самом деле нет, но это хороший минимальный пример, который иллюстрирует проблему, с которой я действительно сталкиваюсь)
Если я раскомментирую свой doubleShow
, я получаю следующую ошибку:
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
Как я могу заставить это работать? Я ожидал, что мои локально определенные имплициты победят любые импортированные из кошек...
Попробуйте неявный объект вместо неявного val
implicit object doubleShow extends Show[Double] {
def show(d: Double) = s"Custom Double Show: $d"
}
или используйте неявный val и измените импорт (не 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"
}
Я быстро нашел другой пример, который не работает: новый вопрос stackoverflow.com/questions/56369317/…
@ user2682459 Тип val doubleShow
— Show[Double]
(такой же, как импортированный из кошек), тип object doubleShow
— doubleShow.type
(плотнее, чем импортированный из кошек). Более конкретные неявные выигрыши.
Как и объектный способ сделать это - мне любопытно, почему объект работает, а val - нет?