The "Combining Total and Ad Hoc Extensible Pattern Matching in a Lightweight Language Extension" paper describes this feature and gives lots of useful and representative examples (A draft of this paper was commented here).
Active patterns are officially available starting with version 1.9.1.8, but version 1.9.1.9 was used for these examples.
One the simplest ways to start defining active patterns on .NET objects is to create one that returns the value of a property. For example, the following active pattern extracts the
FullName
property from System.IO.FileInfo .
let (|FileInfoFullName|) (f:FileInfo) = f.FullName
Now we can using
FileInfoFullName
this way:
let f = (new FileInfo("ActivePatternsTests.exe"))
in
match f with
| FileInfoFullName n ->
Console.WriteLine("File name: {0}",n)
Also active patterns can be used in conjunction with built in F# patterns for example. Given the following active pattern:
let (|FileInfoNameSections|) (f:FileInfo) =
(f.Name,f.Extension,f.FullName)
We can write:
let foo (f:FileInfo) =
match f with
| FileInfoNameSections(_,".txt",fn) -> ("Text file: "+fn)
| _ -> "No text file"
Also active patterns can be combined. For example:
Given these active pattern definitions:
let (|FileSecurity|) (f:FileInfo) = f.GetAccessControl()
let (|NtAccountOwner|) (f:FileSecurity) =
let o = f.GetOwner((typeof() :
ReifiedType< NTAccount >).result) :?> NTAccount
in o.Value
We can write:
let goo (f:FileInfo) =
match f with
| FileSecurity(NtAccountOwner("MyMachine\\auser")) -> "Yes"
| _ -> "No"
Only one kind of active patterns was used in this post, the article describe several others with more interesting characteristics.
More interesting experiments can be done with other .NET APIs. One nice example is LINQ expression trees.