matching multiple patterns at once in ocaml

60 Views Asked by At

Having a custom variant type as below:

type yolo = 
| A of string
| B of yolo
| C of yolo * yolo
| D of yolo * yolo

I also have a function that performs some operations on instances of yolo similar to this:

let rec swag y = 
  match y with
  | A _ -> 1
  | B _ -> 2
  | C (left,right) -> (swag left) + (swag right)
  | D (left,right) -> (swag left) + (swag right)

Since operations for cases C and D are exactly the same I would like to merge them, is it possible?

2

There are 2 best solutions below

0
Jeffrey Scofield On BEST ANSWER

A pattern like pat1 | pat2 matches either of the two patterns:

let rec swag y = 
match y with
| A _ -> 1
| B _ -> 2
| C (left,right) | D (left,right) -> (swag left) + (swag right)

Naturally the two patterns must bind the same names (left and right in this case) with the same types.

0
Chris On

Jeffrey's answer is quite correct. You may wish to consider that if you have several constructors which encode the same information, where the name of the constructor is simply being used as a flag, you might more directly represent that relationship. E.g.

type flag = C | D

type yolo = 
| A of string
| B of yolo
| X of flag * yolo * yolo

And then:

let rec swag y = 
  match y with
  | A _ -> 1
  | B _ -> 2
  | X (_, left, right) -> swag left + swag right

You might also use the function keyword here.

let rec swag = function 
  | A _ -> 1
  | B _ -> 2
  | X (_, left, right) -> swag left + swag right

The pattern Jeffrey has shown also works within patterns.

E.g.

type flag = C | D | E

type yolo = 
| A of string
| B of yolo
| X of flag * yolo * yolo

let rec swag y = function
  | A _ -> 1
  | B _ -> 2
  | X ((C | D), left, right) -> swag left + swag right
  | X (_, left, right) -> ...