haskell - 如何根据两个表达式是否引用相同的绑定(bind)名称来创建重写过程?

标签 haskell compiler-construction

如何查找并重写引用相同绑定(bind)名称的表达式?例如,在表达式中

let xs = ...
in ...map f xs...map g xs...

表达式map f xs和表达式map g xs都引用相同的绑定(bind)名称,即xs。是否有任何标准编译器分析可以让我们识别这种情况并将两个 map 表达式重写为例如

let xs = ...
    e = unzip (map (f *** g) xs)
in ...fst e...snd e...

我一直在思考树遍历的问题。例如给定 AST:

data Ast = Map (a -> b) -> Ast -> Ast
         | Var String
         | ...

我们可以尝试编写一个树遍历来检测这种情况,但这似乎很困难,因为引用相同 Var 的两个 Map 节点可能出现在截然不同的位置在树上。如果您反转 AST 中的所有引用,使其成为一个图表,则此分析似乎更容易完成,但我想看看是否有该方法的替代方案。

最佳答案

我认为您正在寻找的是一组通常称为元组、融合和 super 编译的程序转换,它们属于更一般的展开/折叠转换理论。您可以按如下方式实现您想要的。

首先通过在参数上“驱动”map 的定义来执行推测性评估(展开),这会产生两个新的伪程序,具体取决于 xs 的形式是 y:ys 还是 []。在伪代码中:

let y:ys = ...
in ...(f y):(map f ys)...(g y):(map g ys)...

let [] = ...
in ...[]...[]...

然后对原始程序执行共享结构(元组)和泛化(折叠)的抽象,以阻止其他永久展开:

let xs = ...
in ...(fst tuple)...(snd tuple)...
where tuple = generalisation xs
      generalisation [] = ([],[])
      generalisation (y:ys) = let tuple = generalisation ys
                              in ((f y):(fst tuple),(g y):(snd tuple))

我希望这能给你一个想法,但是程序转换本身就是一个研究领域,如果不绘制无环有向图,很难很好地解释。

关于haskell - 如何根据两个表达式是否引用相同的绑定(bind)名称来创建重写过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12255104/

相关文章:

java - 在 Cmd 中编译 Java 并运行它

haskell 。如何在纯 Haskell 函数中执行 IO?如何在执行函数时打印中间结果?

string - 如何使用parsec获取字符串中特定模式的子字符串

Haskell powerset 函数 - 如何避免无法将预期类型 `IO t0' 与实际类型 `[[Integer]]' 匹配

c - 为什么现代编译器不捕获对数组进行越界访问的尝试?

c++ - C++ 或 C99 理论上可以编译成同样可移植的 C90 吗?

c - 使用 gcc "define but not used"说明符时收到 "__thread"警告

haskell - 在 haskell、Fractional 和 Int 中进行类型转换

haskell - 类型类中的类型与值构造函数

c - 编译器如何在中等内存模型中解析地址?