【问题标题】:Concatenating several values where the type has a Show instance连接类型具有 Show 实例的多个值
【发布时间】:2021-07-27 04:55:06
【问题描述】:

我想编写一个函数showAll,它接受一个List 的值并生成一个String,该String 是通过连接每个值的String 表示获得的,使用隐式范围内可用的Show 实例.

除了Show 实例的存在之外,列表元素的类型应该没有限制。

例如:

case class Person(name: String)
implicit val showPerson: Show[Person] = Show.by(_.name)
showAll(List(1, Person("Martin")))

应该输出:

1 Martin

在这种情况下,函数使用 Show[Int]Show[Person] 实例。

函数的正确签名是什么?

谢谢。

【问题讨论】:

  • 问题是 List 的类型是 List[Any],没有 Show 没有简单的方法来拥有每个元素的 Show。有很多技巧可以得到你想要的,从 magnet 模式,到创建一个自定义类,用它的 show 实例压缩每个元素,再到使用 Shapeless 来做自动压缩。
  • 确实,这就是问题所在。我的第一个想法是添加一些常见的超类型 T,然后为 T 编写一个显示实例,但我想知道是否可以通过某种方式增强签名来解决它。无形看起来很有趣。
  • 检查this (search for the section called "Bonus Round: How do we deal with collections?") - 如果你设法让它工作,请发布答案! :)
  • 你坚持List 还是可变参数也适合你?喜欢showAll(1, person)

标签: scala functional-programming scala-cats


【解决方案1】:

这是我的示例代码,它可能会解决您的问题。 我已经创建了通用方法 show all,因为您需要显示 List 的元素。也是特定字段值的隐式方法。 MyClass 轨迹是标识符。如果 Myclass 不会被任何案例扩展,则不会打印特定类别的字段。

trait Myclass
  case class Person(name: String) extends Myclass
  case class Admin(name: String,age:Long) extends Myclass

  def main(args: Array[String]): Unit = {
    showAll[Myclass](List(1, 2, Person("Martin"),Admin("Bob",30)))
  }

  implicit def showField: String = "name"

  def showAll[T <: Myclass : ClassTag](listOfValues: List[Any]): Unit = {
    listOfValues.foreach { data =>
      if (data.isInstanceOf[T]) {
        val myInstance= data.asInstanceOf[T]
        val fld = myInstance.getClass.getDeclaredField(showField)
        fld.setAccessible(true)
        val value = fld.get(myInstance).asInstanceOf[String]
        print(value + " ")
      }
      else
        print(data + " ")
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 2011-08-02
    相关资源
    最近更新 更多