我注意到我无法使用相同的选项创建两个活动模式,但我可以有两个类似的模式没有任何警告:
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|)
(电流)。
我该如何避免这种情况?
答案 0 :(得分:7)
我同意隐藏活动模式可能会很棘手 - 尽管这与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
答案 1 :(得分:3)
我认为您的关注点一般适用于阴影,而不仅仅适用于活动模式。您多久定义一个参数和返回值相同且具有重叠案例名称的活动模式?通常,类型可以减轻潜在的阴影问题。沿着这些方向,类型注释是你的朋友。