我有正则表达式(RE)的数据结构,到目前为止我没有任何修改RE的函数:
data Regex a = Letter a | Emptyword | Concat (Regex a) (Regex a) | Emptyset | Or (Regex a) (Regex a) | Star (Regex a)
deriving (Show, Eq)
我想为我的RE实现一个简化算法。为此,我认为我应该首先将RE表示为树,根据某些等价更新树,然后将其转换回RE。我的理由是,对于树,我将具有查找,提取和附加子树,更新值等功能。
但是,我很难找到一个提供这些功能的树模块,并且很容易让初学者学习。 我发现这个avl-tree package然而,它看起来非常大。
我希望对我的方法提供替代建议,并提供有关支持所提及功能的简单树模块的建议。 请注意,我是Haskell的初学者,我还不了解monad,并且我对简化RE的实现不感兴趣。
修改1:我们知道以下两个RE是等效的,其中L b
代表Letter b
而C
代表Concat
:< / p>
Or Or
/ \ / \
L b C = L b L a
/ \
L a Emptyword
因此,考虑到左RE,我希望用C
标记的节点替换子树,其节点标记为L a
。正如所指出的,我的数据结构是树结构。但是,目前我没有功能,例如用节点替换子树,或找到我可以替换的结构的子树。
答案 0 :(得分:3)
如评论中所述,您已经有了一棵树。您可以立即简化:
simplify :: Regex a -> Regex a
simplify (Star Emptyset) = Emptyword
simplify (Star (Star x)) = Star (simplify x)
simplify (Concat x Emptyword) = simplify x
simplify (Concat Emptyword y) = simplify y
simplify (Or x y) | x == y = x
-- or rather simplify (Or x y) | simplify x == simplify y = simplify x
-- more sophisticated rules here
-- ...
-- otherwise just push down
simplify (Or x y) = simplify (Or (simplify x) (simplify y)
-- ...
simplify x@(Letter _) = x
这只是肤浅的,例如第一条规则应为simplify (Star x) | simplify x == Emptyset = emptyword
。
AVL树是为了平衡,这里并不适用。平衡有意义的唯一地方是关联操作
Or (x (Or y z) == Or (Or x y) y
我建议将列表用于这些操作
data Regex' a = Letter' a | Concat' [Regex a] | Or [Regex a] | Star (Regex a)
deriving (Show, Eq)
(否Emptyword'
,因为它是Concat' []
;与Emptyset'
和Or
相同。)
在Regex
和Regex'
之间进行转换是读者的惯常做法。
请注意,正则表达式等价并不容易:
(a|b)* = (a*b)*a*
优化Or "(a|b)*" "(a*b)*a*"
很难......