Reputation: 33
Given this type:
type typeT =
| A of int
| B of int
| C of int
| D of int
I want to simplify the following match (returning a default value when matching D, and the identity otherwise):
let match_example_1 t =
match t with
| A x -> A x
| B x -> B x
| C x -> C x
| D x -> D 1
;;
Into something along the lines of this:
let match_example_2 t =
match t with
| D x -> D 1
| f x -> f x
;;
Or this:
let match_example_3 t =
match t with
| f x when f == D -> f 1
| f x -> f x
;;
But i get a syntax error when matching f x
. I'm guessing there's something about what constructors actually are in ocaml and the way pattern matching is actually done that i don't understand. I haven't managed to find the reason though, hopefully someone here can help out.
Upvotes: 0
Views: 225
Reputation: 629
@Théo winterhalter You can use the as construct
match t with
| D _ -> D 1
| (A _ | B _ | C _) as x -> x
I’m on phone so can test where should be the as (inside or outside the parens).
Upvotes: 2
Reputation: 136
You can use the _ shortcut but you will loose the benefit of exhaustivity checking feature
You can also use something like
match t with
A x | B x | C x -> f x
D x -> t
This way if in the future the shape of your datastructure change, the type checker will help you in the refactoring process thanks to exhaustivity checking.
Upvotes: 0
Reputation: 29116
You could also just return the original value if it doesn't match what you're after:
match t with
| D _ -> D 1
| _ -> t
What you propose would only be useful if you want to manipulate the contained value, e.g. f x -> f (x + 1)
, but the questions I asked in the comment above still apply. What if there's a constructor that doesn't follow the exact same shape? What would you expect to happen if you add an E of string
, or an F of int * string
to typeT
?
Upvotes: 1
Reputation: 5108
You cannot do what you want directly. You can factorise a bit by matching several things together.
match t with
| A x
| B x
| C x -> x
| D x -> 1
This will however not allow you to get the A
, B
or C
.
You can however do something closer if you were storing your data differently.
type kind = A | B | C | D
type t = kind * int
And then do
match t with
| (D, x) -> (D, 1)
| (f, x) -> (f, x)
Upvotes: 0