Быстрое решение
Вам просто нужно добавить круглые скобки или begin
/ end
вокруг внутреннего соответствия:
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) ->
<b>(</b>match e2 with
| Sum (e3, e4) -> filter (diffRule e2)
| Diff (e3, e4) -> filter (diffRule e2)
| _ -> filter e2<b>)</b>
| Quot (e1, e2) ->
(match e2 with
| Quot (e3, e4) -> filter (quotRule e2)
| Prod (e3, e4) -> filter (quotRule e2)
| _ -> filter e2)
;;
Упрощения
В вашем конкретном случае нет необходимости во вложенном совпадении.
Вы можете просто использовать большие шаблоны. Вы также можете устранить дублирование во вложенных правилах, используя шаблоны "|
" ("или"):
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
;;
Вы можете сделать его еще более читабельным, заменив неиспользуемые переменные шаблона на _
(подчеркивание).
Это также работает для целых подшаблонов, таких как кортеж (e3,e4)
:
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
;;
Таким же образом вы можете продолжить упрощение. Например, первые три случая (Var
, Sum
, Prod
) возвращаются без изменений, которые можно выразить напрямую:
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
;;
Наконец, вы можете заменить e2
на e
и заменить match
на function
ярлык:
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 хорош, не так ли?