Reputation: 1159
We have this small helper functions
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
And using the active pattern matching function NonEmptyString in the function interface works fine:
let hi (NonEmptyString s) = printfn "Hi %s" s
hi "X" // Hi X
hi "" // System.Exception: String must be non-empty.
Now to the problem.
It would be nice to combine some validators together as a more complex validation constraint, like so
let hi (NonEmptyString s & StartsWithX s) = printfn "Hi %s" s
// error FS0038: 's' is bound twice in this pattern
If only one 's' is allowed, we can think of combining the functions so we have only one argument s. And because active pattern matching functions are functions of course, applying the function composition operator >> but it does not fit here.
let hi (NonEmptyString >> StartsWithX s) = printfn "Hi %s" s
// error FS0010: Unexpected infix operator in pattern
The question is, how can we do that (in F# 4.0) ?
Upvotes: 4
Views: 606
Reputation: 1159
As @kvb commented, the wildcard _ helps in the AND case
// AND
let hi (NonEmptyString _ & StartsWithX s) = printfn "Hi %s" s
The OR case works with with two 's' bindings
// 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.
Note:
This is just for experimenting with composition of Active Pattern Matching as code contracts in a descriptive way at the function interface.
This can be seen as use or misuse of Active Pattern Matching (idiomatic F# or not), it's your choice!
Upvotes: 1