Archive

Archive for July, 2010

Duck typing in C++, F# and C#

C++ templates are very powerful and differs in many ways from generics in C#. One of the things I like about C++ templates is that they allow a kind of statically checked duck typing as examplified below:

struct Customer

{

    int Id; string Name; string Address;

    void Print() const { cout << "id=" << Id << ", name=" << Name << ", address=" << Address << endl; }

};

 

struct Product

{

    int Id; string Name; int Price;

    void Print() const { cout << "id=" << Id << ", name=" << Name << ", price=" << Price << endl; }

};

 

template<class T> int getId(const T& t) { return t.Id; }

template<class T> void print(const T& t) { t.Print(); }

 

void _tmain(int argc, _TCHAR* argv[])

{

    Customer customerSample; customerSample.Id = 66; customerSample.Name = "Egon"; customerSample.Address = "Some street";

    Product productSample; productSample.Id = 24; productSample.Name = "Candy"; productSample.Price = 284;

 

    cout << "Id of customer sample is " << getId(customerSample) << endl;

    cout << "Id of product sample is " << getId(productSample) << endl;

 

    print(customerSample);

    print(productSample);

}

 

The getId and print methods are duck typed in the sense that any class having an Id property, or a Print method respectivly, can be used as an argument. The requirements are statically checked by the compiler which means that if a class is missing the Id property or the print method the program will not compile.

I was happy to discover that F# allows a very similiar solution:

type Customer(id : int, name : string, address : string) =

    member this.Id = id

    member this.Name = name

    member this.Address = address

    member this.Print() = printf "id=%A, name=%A, address=%A\n" id name address

 

type Product(id : int, name : string, price : int) =

    member this.Id = id

    member this.Name = name

    member this.Price = price

    member this.Print() = printf "id=%A, name=%A, price=%A\n" id name price

 

let inline getId arg = ( ^a : (member Id : int) arg )

let inline print arg = ( ^a : (member Print : unit -> unit) arg )

 

let customerSample = Customer(66, "Egon", "Some street 132")

let productSample = Product(24, "Candy", 284)

 

getId customerSample |> printf "Id of customer sample is %A\n"

getId productSample |> printf "Id of product sample is %A\n"

 

print customerSample

print productSample

 

I will not dig into the details but the getId and print functions are more or less equivalent to their C++ counterparts. Matthew Podwysocki provides more information in his blog.

In C# 4 we can use dynamic to achieve this kind of duck typing

class Customer

{

    public int Id { get; set; }

    public string Name { get; set; }

    public string Address { get; set; }

    public void Print() { Console.WriteLine("id={0}, name={1}, address={2}", Id, Name, Address); }

}

 

class Product

{

    public int Id { get; set; }

    public string Name { get; set; }

    public int Price { get; set; }

    public void Print() { Console.WriteLine("id={0}, name={1}, price={2}", Id, Name, Price); }

}

 

class Program

{

    static int GetId(dynamic t)

    {

        return t.Id;

    }

 

    static void Print(dynamic t)

    {

        t.Print();

    }

 

    static void Main(string[] args)

    {

        var customerSample = new Customer { Id = 66, Name = "Egon", Address = "Some street" };

        var productSample = new Product { Id = 24, Name = "Candy", Price = 284 };

 

        Console.WriteLine("Id of customer sample is {0}", GetId(customerSample));

        Console.WriteLine("Id of product sample is {0}", GetId(productSample));

 

        Print(customerSample);

        Print(productSample);

    }

}

 

However, this code is not statically checked by the compiler. Instead the check for the Id property and the Print method is done at runtime. Having the check done at runtime ofcourse makes the code much more fragile.

Categories: Uncategorized

List permutations in F#

let (++) a b = List.append a b

let cons x xs = x::xs

 

let rec permute (xss : ‘a list) : ‘a list list =

    let permuteFirst (ls : ‘a list) : ‘a list list =

        let rec f yss xss =

            match xss with

            | [] -> []

            | x::xs -> (x::yss++xs) :: (f (yss ++ [x]) xs)

        f [] ls

    let permuteRest (lss : ‘a list) : ‘a list list =

            match lss with

            | [] -> raise (new System.Exception());

            | (l::ls) -> List.map (cons l) (permute ls)

    match xss with

    | [] -> []

    | [x] -> [[x]]

    | x::xs -> permuteFirst xss |> List.map permuteRest |> List.concat       

 

permute [1;2;3] gives [[1; 2; 3]; [1; 3; 2]; [2; 1; 3]; [2; 3; 1]; [3; 1; 2]; [3; 2; 1]].

Categories: Uncategorized