Ocaml:匹配表达式在另一个? [英] Ocaml: Match expression inside another one?

查看:59
本文介绍了Ocaml:匹配表达式在另一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在与奥卡姆一起工作一个小项目;一个简单的数学表达式简化。我应该在表达式中找到某些模式,并简化它们,使表达式中的括号数减少。到目前为止,我已经能够实现大多数规则,除了两个,我已经决定创建一个递归的模式匹配过滤器功能。我需要实现的两个规则是:



- 将表单a - (b + c)或类似的所有表达式转换为a - b - c



- 将表单a /(b * c)或类似的所有表达式转换为/ b / c



我怀疑这将是相当简单的,一旦我设法实现一个,我可以轻松地实现另一个。但是,我有递归模式匹配功能的麻烦。我的类型表达是这样的:

  type expr = 
|字符串的变量(*变量*)
| expr的总和* expr(* sum *)
| expr的差异* expr(*差异*)
| expr * expr(* product *)的生成
| expr * expr(*商*)
;;

我主要遇到麻烦,是在匹配表达式中。例如,我正在尝试这样的事情:

  let rec filter exp = 
match exp with
| Var v - > Var v
| Sum(e1,e2) - > Sum(e1,e2)
| Prod(e1,e2)→> Prod(e1,e2)
| Diff(e1,e2)→>
匹配e2与
| Sum(e3,e4) - > filter(diffRule e2)
| Diff(e3,e4)→> filter(diffRule e2)
| _ - >过滤器e2
| Quot(e1,e2) - > ***这行***
匹配e2与
| Quot(e3,e4) - >过滤器(quotRule e2)
| Prod(e3,e4)→>过滤器(quotRule e2)
| _ - >过滤器e2
;;

然而,标记行上的匹配表达式似乎被认为是之前的一部分内匹配而不是主匹配,所以所有的Quot(...)表达式永远不会被识别。甚至可以在这样的其他匹配表达式中匹配表达式吗?那么结束内线比赛的正确方法是什么呢?所以我可以继续匹配其他的可能性?



忽略逻辑,因为我几乎想到了第一个只是我没有能够尝试,因为我必须首先处理这个匹配错误,虽然任何关于如何处理递归或逻辑的建议将是欢迎的。

解决方案

快速解决方案



您只需要添加括号(或开始 / 结束)内部匹配:

 let rec filter exp = 
match exp with
| Var v - > Var v
| Sum(e1,e2) - > Sum(e1,e2)
| Prod(e1,e2) - > Prod(e1,e2)
| (e3,e4) - > filter(diffRule e2)
| Diff(e3,e4) - > filter e4) - > filter(diffRule e2)
| _ - > filter e2
| Quot(e1,e2) - >
(匹配e2与
| Quot(e3,e4) - > filter(quotRule e2)
| Prod(e3,e4) e2)
| _ - > filter e2)
;;

简化



在你的具体情况下不需要一个嵌套的比赛。
您只能使用更大的模式。您也可以使用 | (或)模式消除嵌套规则中的重复:

 让rec filter exp = 
匹配exp与
| Var v - > Var v
| Sum(e1,e2) - > Sum(e1,e2)
| Prod(e1,e2) - > Prod(e1,e2)
| Diff(e1,(Sum(e3,e4)| Diff(e3,e4)为e2)) - > filter(diffRule e2)
| Diff(e1,e2) - > filter e2
| Quot(e1,(Quot(e3,e4)| Prod(e3,e4)as e2)) - > filter(quotRule e2)
| Quot(e1,e2) - > filter e2
;;

您可以通过将 _ (下划线)。
这也适用于整个子模式,如(e3,e4) tuple:

 让rec filter exp = 
匹配exp与
| Var v - > Var v
| Sum(e1,e2) - > Sum(e1,e2)
| Prod(e1,e2) - > Prod(e1,e2)
| Diff(_,(Sum _ | Diff _ as e2)) - > filter(diffRule e2)
| Diff(_,e2) - > filter e2
| Quot(_,(Quot _ | Prod _ as e2)) - > filter(quotRule e2)
| Quot(_,e2) - > filter e2
;;

以同样的方式,您可以继续简化。例如,前三种情况( Var Sum Prod )被返回未修改,您可以直接表达:

  let rec filter exp = 
match exp with
| Var _ | Sum _ |作为e - > e
| Diff(_,(Sum _ | Diff _ as e2)) - > filter(diffRule e2)
| Diff(_,e2) - > filter e2
| Quot(_,(Quot _ | Prod _ as e2)) - > filter(quotRule e2)
| Quot(_,e2) - > filter e2
;;

最后,您可以将 e2 code> e 并将匹配替换为功能快捷方式:

  let rec filter = function 
| Var _ | Sum _ |作为e - > e
| Diff(_,(Sum _ | Diff _ as e)) - > filter(diffRule e)
| Diff(_,e) - > filter e
| Quot(_,(Quot _ | Prod _ as e)) - > filter(quotRule e)
| Quot(_,e) - > filter e
;;

OCaml的模式语法很好,不是吗?


I'm currently working on a small project with Ocaml; a simple mathematical expression simplifier. I'm supposed to find certain patterns inside an expression, and simplify them so the number of parenthesis inside the expression decreases. So far I've been able to implement most rules except two, for which I've decided to create a recursive, pattern-matching "filter" function. The two rules I need to implement are:

-Turn all expressions of the form a - (b + c) or similar into a - b - c

-Turn all expressions of the form a / (b * c) or similar into a / b / c

...which I suspect would be fairly simple, and once I've managed to implement one, I can implement the other easily. However, I'm having trouble with the recursive pattern-matching function. My type expression is this:

type expr =
 | Var of string            (* variable *)
 | Sum of expr * expr       (* sum  *)
 | Diff of expr * expr      (* difference *)
 | Prod of expr * expr      (* product *)
 | Quot of expr * expr      (* quotient *)
;;

And what I'm mainly having trouble on, is in the match expression. For example, I'm trying something like this:

let rec filter exp =   
    match exp with       
    | Var v -> Var v                        
    | Sum(e1, e2) -> Sum(e1, e2)          
    | Prod(e1, e2) -> Prod(e1, e2)
    | Diff(e1, e2) ->
        match e2 with
        | Sum(e3, e4) -> filter (diffRule e2)
        | Diff(e3, e4) -> filter (diffRule e2)      
        | _ -> filter e2         
    | Quot(e1, e2) ->                                 ***this line***
        match e2 with  
        | Quot(e3, e4) -> filter (quotRule e2)        
        | Prod(e3, e4) -> filter (quotRule e2)        
        | _ -> filter e2
;;

However, it seems that the match expression on the marked line is being recognized as being part of the previous "inner match" instead of the "principal match", so all "Quot(...)" expressions are never recognized. Is it even possible to have match expressions inside other match expressions like this? And what would be the correct way to end the inner match so I can continue matching the other possibilities?

Ignore the logic, since it's pretty much what I came up with first, it's just that I haven't been able to try it since I have to deal with this "match" error first, although any recommendation on how to handle the recursiveness or the logic would be welcome.

解决方案

Quick Solution

You just need to add parentheses (or begin/end) around the inner match:

let rec filter exp =
    match exp with
    | Var v -> Var v
    | Sum (e1, e2) -> Sum (e1, e2)
    | Prod (e1, e2) -> Prod (e1, e2)
    | Diff (e1, e2) ->
            (match e2 with
             | Sum (e3, e4) -> filter (diffRule e2)
             | Diff (e3, e4) -> filter (diffRule e2)
             | _ -> filter e2)
    | Quot (e1, e2) ->
            (match e2 with
             | Quot (e3, e4) -> filter (quotRule e2)
             | Prod (e3, e4) -> filter (quotRule e2)
             | _ -> filter e2)
;;

Simplifications

In your particular case there is no need for a nested match. You can just use bigger patterns. You can also eliminate the duplication in the nested rules using "|" ("or") patterns:

let rec filter exp =
    match exp with
    | Var v -> Var v
    | Sum (e1, e2) -> Sum (e1, e2)
    | Prod (e1, e2) -> Prod (e1, e2)
    | Diff (e1, (Sum (e3, e4) | Diff (e3, e4) as e2)) -> filter (diffRule e2)
    | Diff (e1, e2) -> filter e2
    | Quot (e1, (Quot (e3, e4) | Prod (e3, e4) as e2)) -> filter (quotRule e2)
    | Quot (e1, e2) -> filter e2
;;

You can make it even more readable by replacing unused pattern variables with _ (underscore). This also works for whole sub patterns such as the (e3,e4) tuple:

let rec filter exp =
    match exp with
    | Var v -> Var v
    | Sum (e1, e2) -> Sum (e1, e2)
    | Prod (e1, e2) -> Prod (e1, e2)
    | Diff (_, (Sum _ | Diff _ as e2)) -> filter (diffRule e2)
    | Diff (_, e2) -> filter e2
    | Quot (_, (Quot _ | Prod _ as e2)) -> filter (quotRule e2)
    | Quot (_, e2) -> filter e2
;;

In the same way, you can proceed simplifying. For example, the first three cases (Var, Sum, Prod) are returned unmodified, which you can express directly:

let rec filter exp =
    match exp with
    | Var _ | Sum _ | Prod _ as e -> e
    | Diff (_, (Sum _ | Diff _ as e2)) -> filter (diffRule e2)
    | Diff (_, e2) -> filter e2
    | Quot (_, (Quot _ | Prod _ as e2)) -> filter (quotRule e2)
    | Quot (_, e2) -> filter e2
;;

Finally, you can replace e2 by e and replace match with the function shortcut:

let rec filter = function
    | Var _ | Sum _ | Prod _ as e -> e
    | Diff (_, (Sum _ | Diff _ as e)) -> filter (diffRule e)
    | Diff (_, e) -> filter e
    | Quot (_, (Quot _ | Prod _ as e)) -> filter (quotRule e)
    | Quot (_, e) -> filter e
;;

OCaml's pattern syntax is nice, isn't it?

这篇关于Ocaml:匹配表达式在另一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆