我们有这个小助手函数
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",我们可以考虑组合函数,这样我们就只有一个参数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情况与两个的绑定一起使用
// 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#),这是您的选择!