简体   繁体   English

使用Haskell定义普通表单

[英]Defining a normal form with Haskell

I'm trying to get an expression and turn it into a standard form. 我正在尝试获得一个表达式并将其转换为标准形式。 To better clarify my purpose, assume you define a general style for your expressions like this: 为了更好地阐明我的目的,假设您为表达式定义一般样式,如下所示:

∑(a*b) // sum of products Σ(a * b)//产品总和

Now if you're given an input which is not in that format like: (a+b)*(c+d), you'll need to normalize it first.(Actually it is only a simple example and not my case) Now I have a code which is already written in ML and it's too long. 现在,如果你给出的输入不是那种格式,如:(a + b)*(c + d),你需要先将它标准化。(实际上它只是一个简单的例子而不是我的情况)现在我有一个已经用ML编写的代码,它太长了 Here you can see some snipets: 在这里你可以看到一些snipets:

rew(p_choice(x,p_nil)) = rew(x) |
rew(p_choice(p_nil,x)) = rew(x) |
rew(p_sum(d,p_nil)) = p_nil |
rew(p_sum(d,p_choice(x,y))) = rew(p_choice(rew(p_sum(d,x)),rew(p_sum(d,y)))) 
rew(p_cond(b,p_nil,p_nil)) = p_nil |
rew(p_cond(b,p_choice(x,y),p_nil)) =rew(p_choice(rew(p_cond(b,x,p_nil)),rew(p_cond(b,y,p_nil)))) |
rew(p_cond(b,p_sum(x,y),p_nil)) = rew(p_sum(x,rew(p_cond(b,y,p_nil)))) |
rew(p_cond(b1,p_cond(b2,x,p_nil),p_nil)) = rew(p_cond(b1 andalso b2, x,p_nil)) |
rew(p_cond(b,x,p_nil)) = p_cond(b,x,p_nil) |
rew(p_cond(b,x,y)) =
    rew(p_choice(rew(p_cond(b,x,p_nil)),rew(p_cond(not(b),y,p_nil)))) 

My question is, does Haskell introduce any features that can help this code be done more neatly? 我的问题是,Haskell是否引入了任何可以帮助更好地完成代码的功能?

The pattern matching facilities in Haskell are very similar and I don't think the biggest Haskell exclusivities (typeclasses, lazyness, etc) are going to help you. Haskell中的模式匹配工具非常相似,我不认为最大的Haskell排他性(类型,懒惰等)会对你有所帮助。 That said, there might be ways to make things simpler in ML. 也就是说,可能有办法让ML更简单。

One thing to consider is to divide the processing in smaller steps. 要考虑的一件事是将处理分成更小的步骤。 Right now there is some duplication depending if things are the left or the right argument. 现在有一些重复,取决于是左边还是右边的参数。 You could try transforming to an intermediate standard form that chooses one particular order for things. 您可以尝试转换为选择一个特定订单的中间标准表单。

Another trick is separating the processing of each step from the recursion so you don't mix the tree traversal with the node processing. 另一个技巧是将每个步骤的处理与递归分开,这样就不会将树遍历与节点处理混合在一起。 You can write functions to process the stp for each node and then you use a separate fold function to tie everything together. 您可以编写函数来处理每个节点的stp,然后使用单独的折叠函数将所有内容绑定在一起。

data Tree = Leaf Int | Node Tree Tree

directsum :: Tree -> Int
directSum (Leaf n) = n
directsum (Node a b) = (directsum a) + (directsum b)

-- vs

foldtree :: (Int -> r) -> (r -> r -> r) -> Tree  -> b
foldtree onLeaf onNode t =
    go t
  where
    go (Leaf n)   = onLeaf n
    go (Tree a b) = onNode (go a) (go b)

foldedSum :: Tree -> Int
foldedsum t =
    foldtree leafsum nodesum t
  where
    leafsum n = n
    nodesum a b = a + b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM