Сопоставление с образцом F #: как интерпретируется "as" при неправильном использовании с конструктором? - PullRequest
1 голос
/ 08 мая 2020

У меня есть размеченное объединение с выбором, который имеет другой тип du в качестве своего типа, как показано ниже:

type DunionSubset =
    | X
    | Y
type Dunion =
    | A
    | B
    | C of DunionSubset

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

Когда я неправильно использую as для присвоения псевдонима конструктору следующим образом:

let MappingsOfC = function
    | X -> ["x"]
    | Y -> ["y"]

let StringMappings = function
    | A -> ["a";"A"]
    | B -> []
    | C  as c -> (MappingsOfC c)

, компилятор дает мне:

[FS0019] This constructor is applied to 0 argument(s) but expects 1

Как именно неправильное использование мной вышеуказанного приводит к этой ошибке компилятора? Интересно, что ошибка компилятора находится в месте C, а не в моем использовании c в MappingsOfC c, хотя Rider ide подчеркивает c и выдает другую ошибку.

Ответы [ 2 ]

3 голосов
/ 08 мая 2020

C as c сопоставляет аргумент функции с шаблоном C, а также связывает его с c. Таким образом, это то же самое, что:

let StringMappings c = match c with
    | A -> ["a";"A"]
    | B -> []
    | C -> (MappingsOfC c)

, за исключением того, что это сделает c видимым во всех ветвях, тогда как версия с as делает только c видимым в ветке с шаблоном as (естественно).

Вы получаете сообщение об ошибке, потому что C принимает аргумент, но вы пытаетесь использовать его без него. Если вы написали | A as a ->, | B as b -> и / или | C _ as c, это сработает.

2 голосов
/ 10 мая 2020

На самом деле левая часть -> (перед ключевыми словами as и when, если они указаны) в соответствующей ветви - это шаблон . И шаблон должен быть действительным - в зависимости от типа значения, указанного сразу после ключевого слова match.

Здесь компилятор поймет, что вы хотите сопоставить значение Dunion, потому что он видит шаблоны * 1010 Сначала * и B (которые действительны).

Теперь вы можете видеть, что C - недопустимый шаблон для Dunion. Действительный шаблон здесь должен быть: C something

Если вас не волнует something (не нужно его использовать), тем не менее, вы должны предоставить подстановочный знак _, чтобы создать шаблон действительный: C _

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

| C c -> MappingsOfC c
...