Skip to main content

Are you my type?

·2 mins

Did you know there was more to the type matching operator than just pattern matching and exception handling?

The type matching operator is defined thus: :? It can be used by pattern matching to match on a specific type. For example, you might want to test that an object is a certain type or deal with an object being one of several different types. Pattern matching on types is your friend here:

match symbolUse.Symbol with
| :? FSharpMemberOrFunctionOrValue
| :? FSharpUnionCase
| :? FSharpEntity
| :? FSharpField
| :? FSharpGenericParameter
| :? FSharpActivePatternCase
| :? FSharpParameter
| :? FSharpStaticParameter ->
    match getSymbolDeclarationLocation symbolUse currentFile solution with
    | SymbolDeclarationLocation.External -> false
    | SymbolDeclarationLocation.Unknown -> false
    | _ -> true
| _ -> false

During pattern matching you can also use the as assignment operator to assign a named binding to the match so you can use it directly. This is somewhat akin to using is and as in C#, or using an as and then a null check. Yuck! None of that kind of thing in F#:

let isPrivateToFile = 
    match symbolUse.Symbol with
    | :? FSharpMemberOrFunctionOrValue as m -> not m.IsModuleValueOrMember
    | :? FSharpEntity as m -> m.Accessibility.IsPrivate
    | :? FSharpGenericParameter -> true
    | :? FSharpUnionCase as m -> m.Accessibility.IsPrivate
    | :? FSharpField as m -> m.Accessibility.IsPrivate
    | _ -> false

It can also be used in exception handing to match a specific type of exception, as in this example where TimeoutExceptions are caught:

member x.GetDeclarationSymbols(line, col, lineStr) = 
    match infoOpt with 
    | None -> None
    | Some (checkResults, parseResults) -> 
        let longName,residue = Parsing.findLongIdentsAndResidue(col, lineStr)
        // Get items & generate output
            let results = 
                Async.RunSynchronously (checkResults.GetDeclarationListSymbols(Some parseResults, line, col, lineStr, longName, residue, fun _ -> false), timeout = ServiceSettings.blockingTimeout )
            Some (results, residue)
        with :? TimeoutException -> None

A final use for :? that people either don’t tend to use or know about, is during a normal expression assignment. In this example item :? DotNetProject would evaluate to true when item is a DotNetProject.

override x.SupportsItem(item:IBuildTarget) =
    item :? DotNetProject

Although not used that often I find the :? operator to be really useful.

As usual F# helps to keep things short, succinct, and sweet!

Until next time!