scala - 如何删除密封特征实现中的重复 case 语句

标签 scala shapeless

我经常发现我需要在对每个实现执行相同的操作之前提取密封特征的类型:

sealed trait Trait
case class Foo() extends Trait
case class Bar() extends Trait
// ... lots of other implementations

// *must* take a `Trait`, not a `T <: Trait`
def thing(t: Trait): ??? = t match {
  case f: Foo => // something with the instance and specific type
  case b: Bar => // something with the instance and specific type 
  // ... same thing again for other implementations
}

例如

// typically provided by somebody else...
trait Thing[T] { def thingy: String }
implicit def thing[T]: Thing[T] = new Thing[T] { def thingy = "stuff" }

def thing(t: Trait): String = t match {
  case Foo() => implicitly[Thing[Foo]].thingy
  case Bar() => implicitly[Thing[Bar]].thingy
  // ...
}

我想减少执行此操作所涉及的样板。

最佳答案

更新:现在我们将通过无形状使用类型类派生。例如https://github.com/fommil/shapeless-for-mortals

事实证明,您可以使用 shapeless 的多态函数和余积来做到这一点:

  object thing extends Poly1 {
    implicit def action[T <: Trait: Thing] = at[T](
      a => implicitly[Thing[T]].thingy
    )
    // magic that makes it work at the sealed trait level
    def apply(t: Trait): String =
      Generic[Trait].to(t).map(thing).unify
  }

然后可以像这样使用

println(thing(Foo(): Trait))

我希望通过抽象类更容易编写(让我们暂时忘记将隐式参数传递给 action),例如

abstract class MatchSealed[In, Out] extends Poly1 {
  implicit def poly[T <: In] = at[T](action)

  def action[T <: In](t: T): Out

  import ops.coproduct.Mapper
  def apply[R <: HList](in: In)(
    implicit
      g: Generic.Aux[In, R],
      m: Mapper[this.type, R]
  ): Out = {
    val self: this.type = this
    g.to(in).map(self).unify
  }
}

但这失败了,因为最后一行缺少 Mapper[self.type, g.Repr] 。我不知道缺少哪个隐式,但我怀疑它是 self.type。我真的很想捕获 realizedSelf.type 但我不知道该怎么做。

更新:事实证明,无法获取Mapper,因为它需要访问已实现的对象 Unable to map on HList

关于scala - 如何删除密封特征实现中的重复 case 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29651482/

相关文章:

scala - Spark hive udf : no handler for UDAF analysis exception

项目之间的 Scala 代码重用

scala - 如何在托管环境中为 Scala 解释器设置类路径?

scala - 使用 Shapeless 进行泛型类型转换

scala - 在 Shapeless 中,给定两条记录,我如何要求两条记录具有相同的键并将它们连接起来?

用于 Euler 项目 #2 的 Scala 无形代码

scala - 如何解决 java.lang.NumberFormatException : null 问题

Scala:基于类型的列表分区

scala - 如何将通用 HList 转换为列表

Play 框架中的 Scalastyle "Public method must have explicit type"