F#避免活动模式覆盖

时间:2014-11-14 14:51:16

标签: f# active-pattern

我注意到我无法使用相同的选项创建两个活动模式,但我可以有两个类似的模式没有任何警告:

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 个答案:

答案 0 :(得分:7)

我同意隐藏活动模式可能会很棘手 - 尽管这与F#中有区别的联合案例和记录标签的问题相同。如果是类型,您始终可以包含类型名称以解决歧义。

如果是活动模式,您可以将它们放在模块中 - 例如Pat1Pat2

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.APat2.A

let check myvar =
  match myvar with 
  | Pat1.A -> printf "match A\n"
  | n -> printf "match other %A\n" n

答案 1 :(得分:3)

我认为您的关注点一般适用于阴影,而不仅仅适用于活动模式。您多久定义一个参数和返回值相同且具有重叠案例名称的活动模式?通常,类型可以减轻潜在的阴影问题。沿着这些方向,类型注释是你的朋友。