繁体   English   中英

从子类导入隐式

[英]Importing implicits from a subclass

我正在尝试在Scala中实现类型类的一些复杂示例:将类型T的值转换为字符串,该字符串实现为用户可以扩展为任何类型T的库。因此,这是所有类型类应实现的特征:

trait Printable[T] {
  def asString(value: T): String
}

我们要调用以完成工作的函数:

object Printer {
  def print[T](value: T)(implicit p:Printable[T]): String = p.asString(value)
}

具有用于某些默认类型的一系列类型类的对象(例如,仅int&long此处):

object SimpleFormats extends Formats

trait Formats {
  implicit val intFormat = new Printable[Int] {
    override def asString(value: Int) = value.toString
  }
  implicit val longFormat = new Printable[Long] {
    override def asString(value: Long) = value.toString
  }
}

想象一下,用户想要将我们的库扩展为其他类型,例如Float和Double。 因此,他创建了另一个对象,将第一个对象作为子类。 这里的想法是向基础对象添加新的隐式成员,以便可以将类型类的默认集合扩展为任意数量的用户提供的类型:

object ExtendedFormats extends Formats {
  implicit val floatFormat = new Printable[Float] {
    override def asString(value: Float) = value.toString
  }
  implicit val doubleFormat = new Printable[Double] {
    override def asString(value: Double) = value.toString
  }
}

最后,使用我们库的主应用程序。 有两个对不同类型进行操作的示例函数,因此无法提供单个特定的隐式Printer[T]

  • 有多种类型的多种操作
  • Printer事先不知道用户可以提供哪种类型。

因此主应用程序如下所示:

object Example {
  // compiles OK, uses only default typeclasses
  def simpleExample(implicit formats: Formats) = {
    import formats._
    Printer.print(42) + Printer.print(24L)
  }

  // compilation failed, cannot find Printable[Float]
  // uses user-supplied formats
  def extendedExample(implicit formats: Formats) = {
    import formats._
    Printer.print(42f) + Printer.print(31337.0)
  }

  def main(args: Array[String]): Unit = {
    implicit val formats = ExtendedFormats
    println(simpleExample)
    println(extendedExample)
  }
}

我看到scala编译器尝试从Formats导入隐式数据,而忽略了它实际上是ExtendedFormats的事实。

问题:

  • 如示例中所述,是否可以从子类导入隐式方法?
  • 有一批用户提供的类型类更好的解决方案吗?

如果您事先知道您的代码需要Printable用于FloatDouble那么您可以直接声明它:

def extendedExample(implicit floatPrintable: Printable[Float], doublePrintable: Printable[Double]) = {
  Printer.print(42f) + Printer.print(31337.0)
}

或创建类似Format的特征的集合:

trait FormatDouble {
  implicit val doubleFormat: Printable[Double]
}

然后使用它指定所需的类型:

def extendedExample(implicit formats: Formats with FormatDouble with FormatFloat) = {
  import formats._
  Printer.print(42f) + Printer.print(31337.0)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM