Saturday, November 26, 2011

F# ≥ C# (Type extension and GI function)

At previous post, a way to expand class hierarchy and add base class. This post continues to explore the way to expand current system without touching existing code and shows how F# can do the same job with less effort. This post will show who to expand the current type by adding new methods. Also we present a special function can access type without a common base class or interface.

unlike C#'s extension methods, F#'s type extension methods just like the methods on the type. Combining the power from Generic Invoke (GI) function, we can expand current system much easier. The following is the code:
  • the feed function defined at first line is the GI function, it takes any time with a member Feed with signature unit->unit.
  • the original type does not have Feed function. The feed function is from type extension. 
Hopefully from this post and previous post, we have an end-to-end story about how to expand existing system with minimum effort and eventually shows how F# ≥ C#. Please note that CatType and DogType are something not changeable.

// the catType and dogType is from third party and can't change it. 
type CatType =
    | CatA of string
    | CatB of string
    | CatC of string * int
type DogType =
    | DogA of string
    | DogB of string
    | DogC of string * DogType
// code to extension 

let inline feed (x : ^T) = (^T : (member Feed : unit -> unit) (x))
type Animal =
    | Cat of CatType
    | Dog of DogType
// type extension to add a new method: Feed 
type DogType with
    member this.Feed() = printfn "feed dog"
type CatType with
    member this.Feed() = printfn "feed cat"
type Animal with
    member this.Feed() =
        match this with
        | Dog(m) -> feed m
        | Cat(m) -> feed m
let dogs = [ DogA("a"); DogB("a1") ] |> Animal.Dog
let cats = [ CatA("b"); CatB("b1") ] |> Animal.Cat
let zoo = dogs @ cats
zoo |> Seq.iter feed

From the previous post, we have the ability to unify two type into a single list structure, which provide the foundation to process them in a single run.

No comments: