Типы сопоставления записей - PullRequest
2 голосов
/ 18 августа 2011

Давайте рассмотрим следующий Point тип записи:

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

Я хотел бы создать предикат, который скажет мне, находится ли данная точка в допустимой области.

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

Это работает, но мне интересно, есть ли альтернативный способ достижения того же результата, который вместо этого имеет подпись insideBounds

let insideBounds {x=i; y=j}

, все еще используя сопоставление с образцом?

Ответы [ 2 ]

6 голосов
/ 18 августа 2011

Вы можете определить активный шаблон , который проверяет, находится ли значение внутри диапазона, указанного в качестве аргумента:

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

Тогда вы можете определить insideBounds следующим образом:

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

Первый случай соответствует, когда оба члена x и y находятся в указанном диапазоне. Активный шаблон возвращает option unit, что означает, что он не привязывает никаких значений. (0, 100) является входным аргументом, и шаблон соответствует, когда значение (x или y) находится в диапазоне.

(В другом контексте `соответствует 10 с InRange (0

4 голосов
/ 18 августа 2011

Конечно.

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

let insideBounds {x=i; y=j} =
  let notInside c = c < 0 || c > 100
  not (notInside i || notInside j)

Я бы рекомендовал инвертировать вашу логику, чтобы сделать ее более понятной:

let insideBounds {x=i; y=j} =
  let isInside c = c >= 0 && c <= 100
  isInside i && isInside j

Как правило, для булевых функций / свойств и т. Д.быть позитивным.Таким образом, отрицание сохраняет свой негатив, так сказать.

...