类型类的默认隐式对象/定义

时间:2017-05-25 19:13:05

标签: scala typeclass

我要求在runTime中拦截to Date of DateTime,LocalDate和Option。

@implicitNotFound("No member of type class ReportString in scope for ${T}")
trait ReportStringTransformer[T] {
  def toReportString(e: T): String
}

object ReportStringTransformer {
  implicit object ReportStringTransformerDateTime
    extends ReportStringTransformer[DateTime] {
      override def toReportString(e: DateTime): String =
        ISODateTimeFormat.dateTime().print(e)
    }

  implicit object ReportStringTransformerDate
    extends ReportStringTransformer[LocalDate] {
      override def toReportString(e: LocalDate): String =
        ISODateTimeFormat.date().print(e)
    }

  implicit def ReportStringTransformerOpt[T]: ReportStringTransformer[Option[T]] =
    new ReportStringTransformer[Option[T]] {
      override def toReportString(e: Option[T]): String = e match {
        case Some(obj) => ReportStringTransform.transform(obj)
        case None => ""
      }
    }
}

object ReportStringTransform {
  def transform[T](obj: T)(implicit t: ReportStringTransformer[T]): String =
    t.toReportString(obj)
}

我可以在最后添加Any类的默认变换器 在这些之后被接走,但还有其他更清洁的方法吗?

2 个答案:

答案 0 :(得分:2)

您的实施可以简化如下:

@implicitNotFound("No member of type class Show in scope for ${T}")
case class Show[T](f: T => String) extends AnyVal

object Show {
  implicit val showDateTime = Show[DateTime](ISODateTimeFormat.dateTime() print _)
  implicit val showDate = Show[LocalDate](ISODateTimeFormat.date() print _)
  implicit def showOpt[T](implicit s: Show[T]) = Show[Option[T]](_.fold("")(s.f))
}

要对任何不属于这些内容的DateTimeLocalDateOption的内容进行后备,您可以使用以下特征作为{{1}的副本}

object Show

答案 1 :(得分:1)

派对可能迟到了,但你的问题here上的问题是,隐含的解决方案会为你提出的第二种情况选择Some [String]类型。除此之外,OlivierBlanvillain给出的解决方案很棒,它可以解决您的需求。

您可以通过强制转换为Option [String]

来验证这种情况
println(MyShow.show(Some("abc"): Option[String])) // this will work as you expected

使用方差/协方差,可以使其按预期工作link

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))