是否可以将模式用于活动模式的参数?

Is it possible to use patterns for an active pattern's argument?

我有以下活动模式:

let (|IgnoreCase|_|) (arg: string) (input: string) 
    if String.Equals(argument, input, StringComparison.OrdinalIgnoreCase)
    then Some()
    else None

通常,您必须针对每种情况单独使用此模式并执行如下操作:

function
| IgnoreCase "string1" 
| IgnoreCase "string2" 

我想做的是能够将其他匹配表达式与活动模式一起使用,例如:

function
| IgnoreCase ("string1" | "string2") // OR pattern
| IgnoreCase ("string1" & "string2") // AND pattern

returns 错误 “参数化模式标签的参数无效”。我知道你可以使用有区别的联合来做到这一点,所以看起来应该可以使用活动模式。

按照您编写活动模式的方式,它采用字符串参数并检查输入是否与字符串匹配 - 这样,就无法将参数本身转换为模式。

在这种特殊情况下,& 没有任何意义 - 但如果您只想支持 |,您可以传递参数列表:

let (|IgnoreCase|_|) (args: string list) (input: string) =
  if args |> List.exists (fun arg -> 
    String.Equals(arg, input, StringComparison.OrdinalIgnoreCase))
  then Some() else None

function
| IgnoreCase ["string1"; "string2"] -> 1
| _ -> 0

如果您想要更复杂的东西,您需要构建逻辑,以便活动模式 returns 可以进一步匹配的东西。一种选择可能是使用将输入转换为 lower-case 的模式,因为这样您就可以为 lower-cased 字符串指定组合模式:

let (|AsLowerCase|_|) (input: string) =
  Some(input.ToLowerInvariant())

function
| AsLowerCase("string1" | "string2") -> 1
| AsLowerCase("string1" & "string2") -> 1 
| _ -> 0

这使得 & 的语法在语法上有效,但永远不会匹配。但是,您可以有其他模式,例如 StartsWithEndsWith 这样就有意义了,例如写 AsLowerCase(StartsWith "foo" & EndsWith "bar")