Functional_S
Functional_S

Reputation: 1159

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

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

Answers (1)

Functional_S
Functional_S

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

Related Questions