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?