一般重写 Scala 案例类 [英] Generically rewriting Scala case classes

查看:44
本文介绍了一般重写 Scala 案例类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以通用替换案例类中的参数?更具体地说,假设我想要一个替代函数,它接收一个查找"案例类和一个替换"案例类(如语法规则的左侧和右侧)以及一个目标案例类,并且该函数将返回一个带有 find 案例类参数的新案例类替换为替换案例类?该函数还可以简单地采用一个案例类(Product?)和一个要应用于案例类的所有参数/产品的函数.

Is it possible to generically replace arguments in a case class? More specifically, say I wanted a substitute function that received a "find" case class and a "replace" case class (like the left and right sides of a grammar rule) as well as a target case class, and the function would return a new case class with arguments of the find case class replaced with the replace case class? The function could also simply take a case class (Product?) and a function to be applied to all arguments/products of the case class.

显然,给定一个特定的案例类,我可以使用 unapply 和 apply——但是一般(给定任何案例类)编写此类函数的最佳/最简单/等方法是什么?

Obviously, given a specific case class, I could use unapply and apply -- but what's the best/easiest/etc way to generically (given any case class) write this sort of function?

我想知道是否有使用 Scala 2.10 反射功能或 shapeless 的 Iso.hlist 的好的解决方案.

I'm wondering if there is a good solution using Scala 2.10 reflection features or Iso.hlist from shapeless.

例如,我真正想要做的是,给定如下类...

For example, what I really want to be able to do is, given classes like the following...

class Op[T]
case class From(x:Op[Int]) extends Op[Int]
case class To(x:Op[Int]) extends Op[Int]

case class Target(a:Op[Int], b:Op[Int]) extends ...
// and lots of other similar case classes

... 有一个函数可以接受任意 case 类并返回它的副本,其中任何类型为 From 的元素替换为类型 To 的实例.

... have a function that can take an arbitrary case class and return a copy of it with any elements of type From replaced with instances of type To.

推荐答案

如果你原谅这个插件,我想你会发现我们的 Kiama 语言处理库 非常适合这种用途.它提供了一种非常强大的战略规划形式.

If you'll pardon the plug, I think you'll find that the rewriting component of our Kiama language processing library is perfect for this kind of purpose. It provides a very powerful form of strategic programming.

这是一个完整的解决方案,它在由案例类实例构成的树中将 To 重写为 From.

Here is a complete solution that rewrites To's to From's in a tree made from case class instances.

import org.kiama.rewriting.Rewriter

class Op[T]
case class Leaf (i : Int) extends Op[Int]
case class From (x : Op[Int]) extends Op[Int]
case class To (x : Op[Int]) extends Op[Int]

case class Target1 (a : Op[Int], b : Op[Int]) extends Op[Int]
case class Target2 (c : Op[Int]) extends Op[Int]

object Main extends Rewriter {

    def main (args : Array[String]) {
        val replaceFromsWithTos =
            everywhere {
                rule {
                    case From (x) => To (x)
                }
            }

        val t1 = Target1 (From (Leaf (1)), To (Leaf (2)))
        val t2 = Target2 (Target1 (From (Leaf (3)), Target2 (From (Leaf (4)))))

        println (rewrite (replaceFromsWithTos) (t1))
        println (rewrite (replaceFromsWithTos) (t2))
    }

}

输出是

Target1(To(Leaf(1)),To(Leaf(2)))
Target2(Target1(To(Leaf(3)),Target2(To(Leaf(4)))))

replaceFromsWithTos 值的想法是 rule 构造提升了部分函数,​​以便能够对任何类型的值进行操作.在这种情况下,部分函数仅在 From 节点上定义,用 To 节点替换它们.everywhere 组合子表示将我的参数应用于树中的所有节点,保留不适用该参数的不变位置.

The idea of the replaceFromsWithTos value is that the rule construct lifts a partial function to be able to operate on any kind of value. In this case the partial function is only defined at From nodes, replacing them with To nodes. The everywhere combinator says "apply my argument to all nodes in the tree, leaving unchanged places where the argument does not apply.

除了这种简单的重写之外,还有很多事情可以做.请参阅主要的 Kiama 重写文档以了解详细信息,包括指向更多示例的链接.

Much more can be done than this kind of simple rewrite. See the main Kiama rewriting documentation for the gory detail, including links to some more examples.

这篇关于一般重写 Scala 案例类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆