Активный шаблон в предложении совпадения - PullRequest
0 голосов
/ 11 января 2019

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

let (|UpperCase|) (x:string) = x.ToUpper()

let result = match "foo" with
                 | UpperCase "FOO" -> true
                 | _ -> false

Я вижу, мы сравниваем

(Uppercase "foo") with "FOO"

но это выглядит странно в этом случае, когда я читаю

| UpperCase "Foo"

не должен ли этот код быть написан как

let result = match UpperCase "foo" with

Есть ли лучший способ читать?

Ответы [ 2 ]

0 голосов
/ 11 января 2019

В вашем примере вы комбинируете два шаблона : один регистр активный распознаватель без аргументов UpperCase с постоянным шаблоном "FOO". Эффект действительно такой же, как если бы вы применяли функцию (|UpperCase|) внутри выражения соответствия:

match "foo" with
| UpperCase "FOO" -> true
| _ -> false
// val it : bool = true

match (|UpperCase|) "foo" with
| "FOO" -> true
| _ -> false
// val it : bool = true

Теперь сопоставление констант с константами не очень универсально, поэтому давайте вместо этого сделаем функцию.

let isFooBarCaseInsensitive = function
| UpperCase "FOO" | UpperCase "BAR" -> true
| _ -> false
// val isFooBarCaseInsensitive : _arg1:string -> bool
isFooBarCaseInsensitive "foo"
// val it : bool = true
isFooBarCaseInsensitive "fred"
// val it : bool = false

Шаблоны используются не только с ключевыми словами match и function, но также с try...with, fun и, в частности, let:

let (UpperCase foo) = "foo"
// val foo : string = "FOO"
0 голосов
/ 11 января 2019

Думайте о совпадении как об упрощенной цепочке if / else. Например:

match "foo" with
| "foo" -> true    
| _ -> false

Может быть:

if "foo" = "foo" then true
else false

Активные шаблоны - это неявные вызовы функций. В вашем примере:

match "foo" with
| UpperCase "FOO" -> true
| _ -> false

По существу:

if (UpperCase "foo") = "FOO" then true
else false

Вы соответствуете результату нажатия "foo" в вызове, вам просто не нужно указывать его с обычным синтаксисом вызова функции.

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

let UpperCase (x:string) = x.ToUpper()

match UpperCase "foo" with
| "FOO" -> true
| _ -> false

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

Например:

let (|IsInt|IsString|) (x:obj) = match x with :? int -> IsInt | _ -> IsString

match someValue with
| IsInt -> true
| IsString -> false
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...