When reasoning about Active Pattern in F#, its best to start back with Match Expressions.
I looked at Match Expressions in an earlier blog posting.
A match expression is able to decompose an input value and execute different computations or transformations depending on the value.
In the fizzBuzz example above, there are pattern matches for values that are divisible by 3 and for values that are divisible by 5.
The patterns are repeated for the fizzBuzz line and this is obvious code duplication. It would be better to extract the logic and reuse it in the match expression.
Active Pattern provides a clean way of extracting logic that can classify and decompose values. Once formed an Active Pattern can be reused within one or multiple Match Expressions. Here is the fizzBuzz example modified to use an active pattern:
The active pattern is the function DivisibleBy, it is easily recognizable as an Active Pattern because of the presence of banana clips (| |) in the function name.
The rewrite of the fizzBuzz function is not shorter, but it is clearer and the code duplication has been removed. Active patterns come in several flavours and the DivisibleBy function is an example of a Partial Classification Active Pattern.
Active patterns come in the following flavours:
- Partial Classification
Classification Active Pattern
A classifying active pattern applies logic to the input value in order to choose one of the case names that are specified between the banana clips.
This type of active pattern is suited for use within a match expression.
Example returning no values
Example returning values
Classifying Active Pattern distinguishing qualities:
- More than one name between banana clips
- Exhaustive classification
- Optionally return a value
Conversion Active pattern
This type of active pattern does not attempt to classify, it simply converts or decomposes an input value.
This type of active pattern is also called a Single Total Active Pattern.
Because this does not classify then it can’t be used in a match expression, but it is very useful to use in a let binding.
Conversion Active Pattern distinguishing qualities:
- One name between banana clips
- No classification
- Returns a value
Partial Classification Active Pattern
This active pattern attempts to partially classify against a single name between the banana clips, if this matches the input value then it returns Some option value.
If no match, then it returns None. A partial active pattern is easy to spot because of the presence of the wildcard(_) name within the banana clips.
The advantage of creating a partial active patterns is that you can build the logic without coupling it to other cases. Then a match expression can mix and match partial active patterns as needed.
The following example shows partial active patterns that take a parameter.
Partial Classification distinguishing qualities:
- One name and a wildcard(_) between the banana clips
- Non exhaustive classification
- Returns an option value