我注意到我无法使用相同的选项创建两个活动模式,但我可以在没有任何警告的情况下创建两个具有相似选项的活动模式:
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 An"
| n -> printf "match other %An" n
这种情况会发生:
check 'x' // match other 'x'
check 'a' // match other 'a' !!
check '1' // match A
我有点担心无意中覆盖现有的活动模式选项,例如,在同一个单词可能出现在不同模式中的情况下,因为不同的语义上下文,如(|Direct|Indirect|)
(路由)和(|Alternating|Direct|)
(当前)。
如何避免这种情况?
我同意活动模式的阴影可能很棘手 - 尽管这与 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 An"
| n -> printf "match other %An" n
我认为您的担忧适用于一般的阴影,而不仅仅是活跃的模式。您多久定义一次参数和返回值相同且事例名称重叠的活动模式?通常,类型可以缓解潜在的阴影问题。按照这些思路,类型注释是你的朋友。