You do not really need to implement your own chaining of patterns, because you can directly nest the patterns which gives you the required result:
match 20 with
| IfBiggerThan10ThenDouble(IfLessThan100ThenDouble value) -> printfn "%A" value
| _ -> printfn "Did not match"
This will first call the IfBiggerThan10ThenDouble
pattern which calculates 20*2
and passes the value to the nested pattern IfLessThan100ThenDouble
. This again doubles the value and binds it to the value
symbol (when it succeeds).
That said, your implementation of the Chain
pattern actually works and can be called like this:
match 20 with
| Chain (|IfBiggerThan10ThenDouble|_|) (|IfLessThan100ThenDouble|_|) value ->
printfn "%A" value // Should print 80
| _ -> printfn "Did not match"
In general, active pattern (|P|_|)
is really just a function with a special name. You can treat it as an ordinary function and call it by writing (|P|_|) argument
or you can treat it as a value and pass it as an argument to other functions or parameterized active patterns. Your code would work if you implemented Chain
as a pattern taking ordinary functions:
let (|Chain|_|) f g data =
f data |> Option.bind (fun r -> g data)
Then Chain <arg1> <arg2> <pat>
is just calling the parameterized active pattern with two functions as an argument. When called, it binds the result to the pattern <pat>
. In the above example, the two arguments are function values representing the patterns (these could be ordinary functions, but not lambda functions because of syntactic restrictions).