【问题标题】:Simplifying regex in Haskell with trees用树简化 Haskell 中的正则表达式
【发布时间】:2015-01-20 20:26:14
【问题描述】:

我有这个用于正则表达式 (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 bC代表Concat

    Or                          Or
   /  \                        / \
  L b  C            =        L b  L a
      /  \                        
    L a  Emptyword                  

因此,鉴于左边的 RE,我想用 C 标记的根替换子树,并用 L a 标记的节点。正如所指出的,我的数据结构是树形结构。但是,目前我没有功能,例如用节点替换子树,或者找到我可以替换的结构的子树。

【问题讨论】:

  • 您的Regex 数据类型已经是一棵树。
  • 我假设Emptyset 是一个不匹配任何东西的模式?如果是这样,放入那种类型似乎很尴尬,最好将其删除。
  • "...更新树..." - FP 方法是定义 值。如果您提供一个具体示例来说明您希望对正则表达式执行的转换或分析,将会有所帮助。
  • 我很确定这个应用程序不想与 AVL 树有任何关系:-)。
  • @dfeuer EmptySet 当然属于RegEx definition。提示:两个正则的交集也是正则,但可以为空。会提出一个很好的问题,为什么在大多数实现中都缺少空集。

标签: regex haskell tree


【解决方案1】:

如 cmets 中所述,您已经拥有了一棵树。您可以立即简化:

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 树

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 相同。) 在RegexRegex' 之间进行转换是读者的常用练习。

一般硬度

请注意,Regex 等价并不容易:

(a|b)* = (a*b)*a*

优化Or "(a|b)*" "(a*b)*a*" 很难...

【讨论】:

  • 似乎比我的好多了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多