如何在函数表达式中组合 F# 主动模式匹配函数?

How to compose F# Active Pattern Matching functions inside a Function Expression?

我们有这个小辅助函数

open System

let (|NonEmptyString|) value =
    if String.IsNullOrEmpty value
    then failwith "String must be non-empty."
    else value

let (|StartsWithX|) (value:string) =
    if value.StartsWith("X") |> not
    then failwith "String must start with X."
    else value

并且在函数接口中使用主动模式匹配函数 NonEmptyString 工作正常:

let hi (NonEmptyString s) = printfn "Hi %s" s

hi "X"  // Hi X
hi ""   // System.Exception: String must be non-empty.

现在进入正题。

最好将一些验证器组合在一起作为更复杂的验证约束,例如

let hi (NonEmptyString s  &  StartsWithX s) = printfn "Hi %s" s
// error FS0038: 's' is bound twice in this pattern

如果只允许一个's',我们可以考虑把函数组合起来,这样我们就只有一个参数了。 并且因为主动模式匹配函数当然是函数,所以应用函数组合运算符 >> 但它不适合这里。

let hi (NonEmptyString >> StartsWithX s) = printfn "Hi %s" s
// error FS0010: Unexpected infix operator in pattern

问题是,我们如何才能做到这一点(在 F# 4.0 中)?

正如@kvb 评论的那样,通配符 _ 在 AND 情况下有帮助

// AND
let hi (NonEmptyString _  &  StartsWithX s) = printfn "Hi %s" s

OR 案例适用于两个 's' 绑定

// OR
let hi (NonEmptyString s  |  StartsWithX s) = printfn "Hi %s" s
// The logic here makes less sense. It's kept simple with the given helper functions from above.  

注:

这只是为了在函数接口上以描述性方式将活动模式匹配的组合作为代码契约进行实验。

这可以看作是对主动模式匹配的使用或误用(惯用的 F# 与否),由您选择!