Scala 封闭性状的穷举型匹配

Scala 封闭性状的穷举型匹配,scala,Scala,我希望能够完全匹配密封特性实现的类型,如下例所示。理想情况下,我希望尽可能避免使用反射(TypeTags)和隐式转换。有没有办法彻底匹配一个封闭特质的类型 object DataTypes { sealed trait StrFy { def stringify: String } final case class StrFyString(s: String) extends StrFy { def stringify = s } final case

我希望能够完全匹配密封特性实现的类型,如下例所示。理想情况下,我希望尽可能避免使用反射(TypeTags)和隐式转换。有没有办法彻底匹配一个封闭特质的类型

object DataTypes {

  sealed trait StrFy {
    def stringify: String
  }

  final case class StrFyString(s: String) extends StrFy {
    def stringify = s
  }

  final case class StrFyInt(i: Int) extends StrFy {
    def stringify = i.toString
  }

  def stringifyThings[T <: StrFy](values: T*): String = {
    val label = T match {
      case StrFyString => "string"
      case StrFyInt => "integer"
      // cases that don't extend StrFy cause a compile error
    }

    "The " + label + " values are: " + values.map(_.stringify.fold("")(_+", "+_))
  }

  def printStringified(): Unit = {
    println(stringifyThings(StrFyString("foo"), StrFyString("bar"))) // should print: "the string values are: foo, bar"
    println(stringifyThings(StrFyInt(1), StrFyInt(2), StrFyInt(3))) // should print: "the integer values are: 1, 2, 3"
  }
}
对象数据类型{
密封式StrFy{
def stringify:String
}
最后一个case类strfysting(s:String)扩展StrFy{
def stringify=s
}
最后一个案例类StrFyInt(i:Int)扩展了StrFy{
def stringify=i.toString
}
def stringifyThings[T“string”
案例StrFyInt=>“整数”
//不扩展StrFy的情况会导致编译错误
}
“+label+”的值是:“+values.map(u.stringify.fold(“”)(u+”,“++))
}
def printStringified():单位={
println(stringifyThings(strfysting(“foo”),strysting(“bar”))//应该打印:“字符串值是:foo,bar”
println(stringifyThings(StrFyInt(1)、stryint(2)、stryint(3))//应该打印:“整数值是:1、2、3”
}
}

除非使用“无隐式”排除的typeclass,否则无法获得给定类型的值。因此,需要与实例进行匹配

object DataTypes extends App {

  sealed trait StrFy {
    def stringify: String
  }

  final case class StrFyString(s: String) extends StrFy {
    def stringify = s
  }

  final case class StrFyInt(i: Int) extends StrFy {
    def stringify = i.toString
  }

  def stringifyThings[T <: StrFy](values: T*): String = {
    def label(value: T) = value match {
      case _:StrFyString => "string"
      case _:StrFyInt => "integer"
      // cases that don't extend StrFy cause a compile error
    }
    // Will throw if values is empty
    "The " + label(values.head) + " values are: " + values.map(_.stringify).mkString(", ")
  }

  def printStringified(): Unit = {
    println(stringifyThings(StrFyString("foo"), StrFyString("bar"))) // should print: "the string values are: foo, bar"
    println(stringifyThings(StrFyInt(1), StrFyInt(2), StrFyInt(3))) // should print: "the integer values are: 1, 2, 3"
  }
  printStringified()
}
编译器为您执行“模式匹配”,提供给定输入类型的正确实例。
您可以看到,typeclass允许您在这里获得一个值,这里是只给定一个类型的标签。这是一个非常基本的概念,使得类typeclass的多态性比子类型的多态性更强:)

对于
stringifyThings(strfysting(“s”),StrFyInt(9))
,您应该得到一个错误(stringifyThings必须采用同质列表)
object DataTypes extends App {

  sealed trait StrFy[T] {
    def stringify(value: T): String
    def label: String
  }

  implicit object StrFyString extends StrFy[String] {
    override def stringify(value: String): String = value
    override def label: String = "string"
  }
  implicit object StrFyInt extends StrFy[Int] {
    override def stringify(value: Int): String = value.toString
    override def label: String = "integer"
  }

  def stringifyThings[T: StrFy](values: T*): String = {
    val strFy = implicitly[StrFy[T]]
    // Safe even on empty values
    "The " + strFy.label + " values are: " + values.map(strFy.stringify).mkString(", ")
  }

  def printStringified(): Unit = {
    println(stringifyThings("foo", "bar")) // should print: "the string values are: foo, bar"
    println(stringifyThings(1, 2, 3)) // should print: "the integer values are: 1, 2, 3"
  }
  printStringified()
}