Last week I was pointed by someone to Active Patterns in F#. And it has been quite an interesting discovery.

Active Patterns are used on F# to partition data. Those partitions then can be used with pattern matching. Microsoft's webpage compares them to discriminated unions.

How they can be used? Well, you could look at the above link, or just follow this post (or, in fact, do both).

Below is an initial version of a trivial function using pattern matching.

```
let thisNumberTrait(number) =
match number with
| x when x = 0 -> "Is Zero!!"
| x when x > 0 -> "Is Positive!!"
| x when x < 0 -> "Is Negative!!"
| _ -> "I shouldn't be here"
```

A first improvement of the above code would be to put the logic on the guards behind functions, so we can arrive to this:

```
let isZero(number) = number = 0
let isPositive(number) = number > 0
let isNegative(number) = number < 0
let thisNumberTrait(number) =
match number with
| x when isZero(x) -> "Is Zero!!"
| x when isPositive(x) -> "Is Positive!!"
| x when isNegative(x) -> "Is Negative!!"
| _ -> "I shouldn't be here"
```

But what if we could remove the guard clauses completely? That is where Active Patterns come into play.

```
let (|Zero|_|) (number) = if number = 0 then Some(number) else None
let (|Positive|_|) (number) = if number > 0 then Some(number) else None
let (|Negative|_|) (number) = if number < 0 then Some(number) else None
let thisNumberTrait(number) =
match number with
| Zero(x) -> "Is Zero!!"
| Positive(x) -> "Is Positive!!"
| Negative(x) -> "Is Negative!!"
| _ -> "I shouldn't be here"
```

As you can see there are a few differences on the code. If we concentrate on the logic functions, we can see that now the name of the function has been changed for the construct `(| | |)`

, and that now is it returning an Option type. Then, the pattern matching has replaced the `x when ...`

code with the new Pattern `Zero(x)`

. We complicate a bit the functions, we simplify the pattern matching.

If we look at what is the answer that we are providing, we realize that we are not using the number at all, so in fact we could change the line

```
| Zero(x) -> "Is Zero!!"
```

for

```
| Zero(_) -> "Is Zero!!"
```

The `x`

is not the data that we pass to the Pattern, is the data that is returned! We pass the data implicilty. But wait, if I don't use the return data, do I need to return it at all? And the answer is no. So now we replace

```
let (|Zero|_|) (number) = if number = 0 then Some(number) else None
```

with

```
let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None
```

We return the name of the pattern, instead of the data.

Which now means that on the match we can do the change from

```
| Zero(_) -> "Is Zero!!"
```

to

```
| Zero -> "Is Zero!!"
```

So far we have returned the same data that we have passed, and not returned anything. But what if we want to return data of a different type? That is possible: Look below that `(|Positive|_|)`

returns a string now.

```
let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None
let (|Positive|_|) (number) = if number > 0 then Some("Positive") else None
let (|Negative|_|) (number) = if number < 0 then Some(number) else None
let thisNumberTrait(number) =
match number with
| Zero -> "Is Zero!!"
| Positive(x) -> sprintf "Is %s!!" x
| Negative(_) -> "Is Negative!!"
| _ -> "I shouldn't be here"
```

So far I have been using Partial Patterns. That is, the data could not be defined as a partition. That is why there is an underscore (`(|Zero|_|)`

) and why we are returning an Option (Some|None). But we could have a full Active Pattern, where the data must be inside one of the partitions. The changes are easy just as below)

```
let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None
```

to

```
let (|Zero|NonZero|) (number) = if number = 0 then Zero else NonZero
```

Patterns can be combined using `&`

for the and combination, and `|`

for the or combination.

So instead of

```
| Positive(x) -> sprintf "Is %s!!" x
```

we could write

```
| NonZero & Positive(x) -> sprintg "Is %s!!" x
```

Not that in this case makes any difference, but is a posibility.

Finally, we could make single big pattern, replacing

```
let (|Zero|_|) (number) = if number = 0 then Some(Zero) else None
let (|Positive|_|) (number) = if number > 0 then Some(Positive) else None
let (|Negative|_|) (number) = if number < 0 then Some(Negative) else None
```

with

```
let (|Zero|Positive|Negative|) (number) = if number = 0 then Zero elif number > 0 then Positive else Negative
```

Which in this case looks a bit pointless to me, as I'm nearly back to the original code. It will have it's uses, though.

Active Patterns are an intersting construct, especially when using the Active Pattern multiple times.

Although he started early (with QuickBasic and Turbo Pascal), took him a while to center into the developer way of living. Nonetheless, he has more than 10 years experience as software developer at different levels. His main experience is around C# and .Net, but has a keen interest in other languages, especially around functional programming.

In his experience two maxims have been revealed, Simple is Beautiful and Make Everyone's Life Easy. Because of them, his personal goal is to improve the experience of fellow developers (which always translates to happy customers)

Outside of work, you can find him either playing online or dancing away, or just improving his craft (that is the way of the developer).

All author postsSoftware es nuestra pasión.

Somos Software Craftspeople. Construimos software bien elaborado para nuestros clientes, ayudamos a los desarrolladores a mejorar en su oficio a través de la formación, la orientación y la tutoría y ayudamos a las empresas a mejorar en la distribución de software.

John Hearn

Mashooq Badar

Liam Griffin-Jowett

London EC1V 0JR

Teléfono: +44 207 4902967

2 Mount Street

Manchester M2 5WQ

Teléfono: +44 207 4902967

Carrer Aragó, 208

08011, Barcelona

Teléfono: +34 937 82 28 82

Correo electrónico: hello@codurance.es