Я хотел бы преобразовать кортеж из двух элементов одного типа в список. Код выглядит просто:
let toList (tuple: 'a * 'a): 'a list =
match tuple with
| (_ as fst, _ as snd) -> [fst; snd]
Но почему-то типом snd
является 'a * 'a
, поэтому кажется, что вместо привязки второго элемента кортежа к переменной вместо этого привязывается весь кортеж. Это ошибка в компиляторе или я что-то пропустил?
Фактический код более сложен, поэтому идея состоит не в том, чтобы переписать предоставленную часть, а в том, чтобы понять, что не так с использованием as
здесь. Я ожидаю, что as
должен идти после кортежа, чтобы связать его в целом, вот так | (_ as fst, _ as snd) as tuple
Правильная синтаксическая форма шаблона «как»
погладить как идент.
Это определяет идентификатор равным вводу шаблона и соответствует вводу шаблона. против пат.
Для вашего кода это означает
let toList (tuple: 'a * 'a): 'a list =
match tuple with
| (fst, snd) -> [fst; snd]
где (fst, snd)
— шаблон кортежа.
См. Спецификацию языка F# в разделе 7.3 для получения полной информации о шаблоне as.
Для практических целей ответ @nilekirk лучше: вам вообще не нужно as
в этом конкретном случае.
Но если вам интересно, почему snd
имеет этот тип для целей обучения, вот объяснение.
Ваш шаблон компилируется следующим образом:
| ((_ as fst, _) as snd) ->
То есть кортеж связывает сильнее, чем сглаживание шаблонов.
Если вы хотите, чтобы каждый as
применялся к одному элементу кортежа, вам нужно явно указать компилятору, как заключать их в скобки:
| ((_ as fst), (_ as snd)) ->
И, кстати, в F# кортежи не обязательно должны быть в скобках, поэтому внешние скобки не нужны:
| (_ as fst), (_ as snd) ->
Как я уже говорил, переписывать код в какой-то другой вид мне не нужно, так как на самом деле все сложнее: используется шаблон идентификатора, и мне нужно одновременно проверять тип DU и извлекать элемент кортежа. Принятие твоего. Спасибо!