Search code examples
f#type-extension

F# - Type augmentation VS Type extension


What exactly is the difference between F#'s type augmentation and type extension, and do we really need both?

Are there situations where one is better than the other, and vice-versa?

I'm asking because I recently had a lecture in F# where the lecturer talked about both, and afterwards commented that he couldn't see the reason why both were included in the F# language.

Update:

Ok, so Vladislav Zorov links to a page with examples of using type augmentation both when defining your own types, and extending (or augmenting?) an external type.

pad links to an MSDN page where they call it intrinsic and optional type extension.

Both seem to illustrate the same thing. Can someone come with a concrete example of type extension and another concrete example of type augmentation perhaps, in order to explicitly clarify what the two things are exactly?


Solution

  • The following bits from MSDN's Type Extensions page are relevant (emphasis mine):

    There are two forms of type extensions that have slightly different syntax and behavior. An intrinsic extension is an extension that appears in the same namespace or module, in the same source file, and in the same assembly (DLL or executable file) as the type being extended. An optional extension is an extension that appears outside the original module, namespace, or assembly of the type being extended. Intrinsic extensions appear on the type when the type is examined by reflection, but optional extensions do not. Optional extensions must be in modules, and they are only in scope when the module that contains the extension is open.

    The purpose of optional extension is clear. It helps you inject new functionalities to types not belonging to your assemblies. For examples, FSharpx uses it to create various helpers for parsing primitive types:

    open System
    
    type Boolean with
        static member parse x =
            match bool.TryParse(x) with
            | true,v -> Some v
            | _ -> None
    

    Why do you need intrinsic extension then? The answer is its convenience. I find it useful to break down type definitions to multiple sections with clear purposes.

    In many F# libraries, I saw the use of the following pattern: type definition -> utility functions -> intrinsic extension. In this way, you can define sophisticated utility functions on your types, make them available in modules and still can use them directly in your member definitions. You can look at Complex type in F# PowerPack to see the pattern.

    EDIT:

    To be honest, I often use type extension and type augmentation interchangeably. The thing that matters is whether they are intrinsic or optional.