F# Избегайте активной перезаписи паттернов
Я заметил, что не могу создать два активных шаблона с одинаковыми параметрами, но у меня может быть два с одинаковыми без предупреждения:
let (|A|B|C|) c =
if (c = 'a') then A
else if (c = 'b') then B
else C
let (|A|B|D|) c =
if (c = '1') then A
else if (c = '2') then B
else D
Итак, при сопоставлении таким образом:
let check myvar =
match myvar with
| A -> printf "match A\n"
| n -> printf "match other %A\n" n
Бывает:
check 'x' // match other 'x'
check 'a' // match other 'a' !!
check '1' // match A
Я немного обеспокоен непреднамеренной перезаписью существующих активных вариантов шаблона, например, в ситуациях, когда одно и то же слово может появляться в разных шаблонах, потому что разные семантические контексты, такие как (|Direct|Indirect|)
(маршрут) и (|Alternating|Direct|)
(ток).
Как я могу избежать этой ситуации?
2 ответа
Я согласен, что затенение активных шаблонов может быть непростым делом - хотя это та же проблема, что и с дискриминационными случаями объединения и метками записей в F#. В случае типов вы всегда можете включить имя типа, чтобы устранить неоднозначность.
В случае активных паттернов вы можете поместить их в модули - например, Pat1
а также Pat2
:
module Pat1 =
let (|A|B|C|) c =
if (c = 'a') then A
else if (c = 'b') then B
else C
module Pat2 =
let (|A|B|D|) c =
if (c = '1') then A
else if (c = '2') then B
else D
Таким образом, в вашем коде вы можете использовать полное имя, например Pat1.A
или же Pat2.A
:
let check myvar =
match myvar with
| Pat1.A -> printf "match A\n"
| n -> printf "match other %A\n" n
Я думаю, что ваши опасения касаются в целом теневого копирования, а не только активных моделей. Как часто вы будете определять два активных шаблона, параметры и возвращаемые значения которых совпадают и имеют перекрывающиеся имена падежей? Как правило, типы смягчают потенциальные проблемы с теневым копированием. Вдоль этих строк, аннотации типа ваш друг.