Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching record types

Let's consider the following Point record type:

type Point = { x:int; y:int }

I'd like to make a predicate that tells me whether a given Point is in a valid region.

let insideBounds p =
  let notInside c = c < 0 || c > 100
  match p with
  | {x=i; y=_} when notInside i -> false
  | {x=_; y=j} when notInside j -> false
  | _                           -> true

This works, yet I wonder if there's an alternative way of achieving the same result having as insideBounds signature

let insideBounds {x=i; y=j}

instead, still making use of pattern matching?

like image 534
devoured elysium Avatar asked Feb 06 '26 15:02

devoured elysium


1 Answers

You can define an active pattern that tests whether a value is inside a range specified as an argument:

let (|InRange|_|) (min, max) v = 
  if v >= min && v <= max then Some () else None

Then you can define insideBounds like this:

let insideBounds = function
  | { x = InRange (0, 100); y = InRange (0, 100) } -> true
  | _ -> false

The first case matches when both x anad y members are in the specified range. The active pattern returns option unit, which means that it doesn't bind any values. The (0, 100) is an input argument and the pattern matches when the value (x or y) is in the range.

(In other context `match 10 with InRange (0

like image 135
Tomas Petricek Avatar answered Feb 09 '26 08:02

Tomas Petricek