折叠多项式分析树的最有效方法

问题描述

我正在研究符号代数系统。我目前正在研究如何从二叉分析树执行多项式加法/乘法。稍后我会认为这是一个普通戒指。

解析在这里相关——这旨在成为解析的输出。形成的解析树。如果这里有什么可以改进的地方,我当然也很高兴了解这一点。

我“感觉”这个树结构可以折叠/压碎,但我不太清楚如何去做。我相信我可以一起破解一些东西,但由于我仍在学习 Haskell,我想了解更高级的用户会做什么。

以下是相关代码背景。

我的两个相关数据声明是:

data Op = Add | Mul
data Tree a = Leaf a | Node Op [Tree a] [Tree a]

这是我的测试示例之一:

-- 3*(x+2)*(x+(5*4))
test = Node Mul [
         Node Mul 
          [Leaf "3"] 
          [Node Add 
            [Leaf "x"] 
            [Leaf "2"]
          ]
         ] 
         [Node Add 
           [Leaf "x"] 
           [Node Mul 
             [Leaf "5"] 
             [Leaf "4"] 
           ]
         ]

这是一种典型的递归树类型,其中一个节点包含一个操作以及左树和右树的列表。计算通过以下操作进行。注意:它们现在都是字符串操作。我需要它们尽可能通用(但稍后会添加进一步的结构,如乘法交换性)。

prod :: [Tree [a]] -> [Tree [a]] -> [Tree [a]]
prod ls rs = [Leaf (l ++ r) | (Leaf l) <- ls,(Leaf r) <- rs]

add :: [Tree [a]] -> [Tree [a]] -> [Tree [a]]
add l r = l ++ r

opOnLeaf :: Op -> [Tree [a]] -> [Tree [a]] -> [Tree [a]]
opOnLeaf op l r  
  | op == Add = add l r
  | op == Mul = prod l r

operate :: Tree [a] -> [Tree [a]]
operate (Node op [Node op2 l2 r2] [Node op3 l3 r3]) = operate (Node op (operate (Node op2 l2 r2)) (operate (Node op3 l3 r3)))
operate (Node op [Node op2 l2 r2] r) = operate (Node op (operate (Node op2 l2 r2)) r)
operate (Node op l [Node op2 l2 r2]) = operate (Node op l (operate (Node op2 l2 r2)))
operate (Node op l r) = opOnLeaf op l r

我认为 operate 中的变量名很糟糕,但我想确保它首先起作用。让它变得丑陋也使它更加突出。这实际上是在对我大喊大叫,让我找到更好的方法。

现在,我想使用 fold 或 foldMap,但我遇到了在每个操作(即 (*)(+))中都有不同幺半群的问题。而这只是开始——我将添加其他几个操作。所以我需要像“可变幺半群”之类的东西,或者可能是其他一些地图,其操作是首先获取幺半群。我不确定。

查询:给定这个二叉树,每个节点有多个操作,如何折叠结构?有没有更好的方法可以将其编写为可折叠的实例或其他结构?我还打算添加其他几个二进制操作。理想情况下,我想要一个可以无限扩展的结构。我假设一旦解决了 2,我们就可以有效地解决 n。

Tree drawing corresponding to test example

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)