3

我注意到我无法创建两个具有相同选项的活动模式,但我可以在没有任何警告的情况下创建两个具有相似选项的模式:

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|)(当前)),同一个词可能出现在不同的模式中。

我怎样才能避免这种情况?

4

2 回答 2

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.Aor Pat2.A

let check myvar =
  match myvar with 
  | Pat1.A -> printf "match A\n"
  | n -> printf "match other %A\n" n
于 2014-11-14T15:15:43.883 回答
3

我认为您的担忧通常适用于阴影,而不仅仅是活动模式。您多久会定义两个参数和返回值相同且案例名称重叠的活动模式?通常,类型可以缓解潜在的阴影问题。沿着这些思路,类型注释是你的朋友。

于 2014-11-14T15:12:28.277 回答