
Active Patterns


Fundamentals of Active Patterns 


An active pattern is a special name that either you can use as a
function or you can involve in pattern matching.
The primary formula to create an active pattern for a function is:

let (functionname) [ argument(s) ] = body
You start with the let keyword followed by parentheses. In the parentheses, add two pipes. Inside the pipes, add a name for a function. By tradition, the name inside the pipes uses the convention for types.
Here is an example:
let (Show) . . .
Outside the parentheses, if the function will not take an argument, type some empty parentheses or an underscore. This is followed by the normal = sign of a regular function. As you know already, the section after = is the body of the function. If you are not planning to do anything significant, you can use () as the whole body of the function. Here is an example:
let (Show) _ = ()
Using a Functional Active Pattern


The function as we have just created it is primarily a regular function like any other. This means that you can
use it when necessary. To call the function, include it in its pipes and parentheses. If the function didn’t take any argument, make sure you add empty parentheses to it. Here is an example:
let (Show) _ = ()
(Show)()
This would produce:
Press any key to continue . . .
You can make the function behave like any other. For example, in its body, you can display something. Here is an example:
let (Show) _ = printfn "The wonderful world of functional programming"
(Show)()
This would produce:
The wonderful world of functional programming
Press any key to continue . . .
You can pass an argument to the function. This is done just
after the parentheses of the function name. Here is an example:
let (Calculate) x = ...
Of course, you can specify the data type of the argument. In
this case, you must include it in parentheses, with its type, both separated by
a colon. This would be done as follows:
let (Calculate) (x : float) = ...
In the body of the function, use the argument as you see fit. Here is an example for a function used to calculate the area of a circle while its argument represents the radius of the circle:
let (Calculate) x = x * x * 3.14
You can then call the function and pass the desired value to it. Here is an example:
let (Calculate) x = x * x * 3.14
let area = (Calculate) 25.50
printfn "Area of Circle: %0.04f" area
This would produce:
Area of Circle: 2041.7850
Press any key to continue . . .
Otherwise, you can declare a variable for the argument that you will pass to the function. Here is an example:
let (Calculate) x = x * x * 3.14
let radius = 48.79
let area = (Calculate) radius
printfn "Circle Characteristics"
printfn ""
printfn "Radius: %0.02f" radius
printfn "Area: %0.04f" area
This would produce:
Circle Characteristics

Radius: 48.79
Area: 7474.6573
Press any key to continue . . .
In the same way, you can pass as many arguments as you want,
and you can use the arguments any way you want. Here is an example:
let (Calculate) x y = x * y
let length = 48.79
let height = 33.63
let area = (Calculate) length height
printfn "Rectangle Characteristics"
printfn ""
printfn "Length: %0.02f" length
printfn "Height: %0.02f" height
printfn "Area: %0.04f" area
This would produce:
Rectangle Characteristics

Length: 48.79
Height: 33.63
Area: 1640.8077
Press any key to continue . . .
Of course, you can do more than a short simple calculation in the function.
Matching an Active Pattern


An active pattern can be used as the expression of a matching pattern. Here is an example:
let (Show) _ = ()
match (Show) with
If the active pattern was created as a function, the matching pattern should have only one option. If the function of the active pattern didn’t take an argument, you can use anything as the option of the matching pattern. Here is an example:
let (Show) _ = ()
match (Show) with
 anything >
Since that option doesn’t hold any value, it cannot be used; it is just an empty insignificant value. Therefore, as an alternative, you can use the underscore. Here is an example:
let (Show) _ = ()
match (Show) with
 _ >
In the body of the option, you can call the function if you want. In this case, you must use the whole name, including its parentheses and pipes. If the function didn’t take an argument, add some empty parentheses to it. Here is an example:
let (Show) _ = ()
match (Show) with
 _ > (Show)()
As seen earlier, you can put any statement of your choice in the
body of the function, such as displaing something. Here is an example:
let (Show) _ = printfn "The wonderful world of functional programming"
match (Show) with
 _ > (Show)()
This would produce:
The wonderful world of functional programming
Press any key to continue . . .
You can also use the option in the pattern matching any way you want, such as displaying a value. Here is an example:
let (Show) _ = ()
match (Show) with
 _ > printfn "This is the wonderful world of F# programming"
This would produce:
This is the wonderful world of F# programming
Press any key to continue . . .
In most cases, you create a functional active pattern because you want to perform an operation. In this case, you should pass an argument
to the function. In the body of the function, use the argument as you see fit. Here is an example
we saw earlier:
let (Calculate) x = x * x * 3.14
As we saw earlier, you can then call the function and pass the desired value to it. You can also call the function as the pattern to match and pass the necessary value for its argument. Here is an example:
let (Calculate) x = x * x * 3.14
match (Calculate) 25.50 with
 _ > printfn "Area of Circle: %0.04f" ((Calculate) 25.50)
Or you can declare a variable for the argument, initialize
that variable, and pass it to the function. Here is an example:
let (Calculate) x = x * x * 3.14
let radius = 48.79
let area = (Calculate) radius
match area with
 _ > printfn "Area of Circle: %0.04f" area
Of course, you can create more than one statement in the
pattern matching. Here is an example:
let (Calculate) x = x * x * 3.14
let radius = 48.79
let area = (Calculate) radius
match area with
 _ > printfn "Circle Characteristics"
printfn ""
printfn "Radius: %0.02f" radius
printfn "Area: %0.04f" area
This would produce:
Circle Characteristics

Radius: 48.79
Area: 7474.6573
Press any key to continue . . .
Remember that you can pass as many arguments as you want to
the function. Here is an example we saw earlier:
let (Calculate) x y = x * y
let length = 48.79
let height = 33.63
let area = (Calculate) length height
match (Calculate) length height with
 _ > printfn "Rectangle Characteristics"
printfn ""
printfn "Length: %0.02f" length
printfn "Height: %0.02f" height
printfn "Area: %0.04f" area
You can also call the function as the option of the pattern
matching. If the function was passed an argument, you can pass it any name as
argument. Here is an example:
let (Calculate) x = x * x * 3.14
let radius = 48.88
match radius with
 Calculate something > printfn "Area: %0.04f" something
Active Patterns and Lambda Expressions


Instead of passing an argument to the function. you can
create a lambda expression in the body of the function. That lambda expression
can take the argument. Here is an example:
let (Calculate) = fun x > x * x * 3.14
Of course, you can specify the data type of the argument.
Here is an example:
let (Calculate) = fun (x : float) > x * x * 3.14
When calling the function, pass the desired value as argument. Here is an example:
let (Calculate) = fun (x : float) > x * x * 3.14
let area = (Calculate) 25.50
printfn "Area of Circle: %0.04f" area
If necessary, the lambda expression can take as many arguments as you want. Here is an example:
let (Calculate) = fun x y > x * y
let length = 48.79
let height = 33.63
let area = (Calculate) length height
printfn "Rectangle Characteristics"
printfn ""
printfn "Length: %0.02f" length
printfn "Height: %0.02f" height
printfn "Area: %0.04f" area
In the same way, the function can be called in a
matching pattern with the right arguments. Here is an example:
let (Calculate) = fun x y > x * y
let length = 48.79
let height = 33.63
let area = (Calculate) length height
match (Calculate) length height with
 _ > printfn "Rectangle Characteristics"
printfn ""
printfn "Length: %0.02f" length
printfn "Height: %0.02f" height
printfn "Area: %0.04f" area
