How to write generic, duck-typing code in F#

When writing generic code in C++, it’s easy to imply constraints in the generic type when developing a template. For example:

template<class T> 
class Announcer{
public:
	static void announce( const T& t )
	{
		std::cout << "And now from " <<  t.country << ", we have: ";
		bool first = true;
		for ( auto person : t.people )
		{
			std::cout << person;
			if (!first) std::cout << "\n";
			first = false;
		}
	}
};

Here, we’re assuming that T has two properties, ‘country’ and ‘people’, with the latter being enumerable (i.e. supports begin/end methods and iterators). This is one of the attractions of C++ for generic code – although, in the future, concepts will enable you to document the constraints in order to make it easier for developers to use your library, and for the compiler to give clearer errors.

What about something similar in F#? I found Tomas Petricek’s post from StackOverflow very useful.

type IHasCountryProperty =
    abstract Country : string

type Announcer<'T when 'T :> IHasCountryProperty>( item : 'T) =
    member this.Announce() =
        printfn "And now the party from %s" item.Country

let inline countrifiedItem<'T when 'T : (member Country : string)> (item : 'T) =
    {
        new IHasCountryProperty with
            member this.Country = (^T : (member Country : string) item)
    }

type London() =
    member this.Country = "England"

// Use it
let city = London()
Announcer( countrifiedItem city ).Announce()

The Announcer class uses a member constraint with statically resolved type parameters which bind to the Country property. Then, the inline static function ‘countrifiedItem’ uses static member constraints to capture the existing Country property on any other type, even if like ‘London’ it doesn’t support the IHasCountryProperty. The consensus seems to be that this approach is encouraged because it documents the requirements on ‘T in an interface.

Leave a comment

Filed under C++, C++ Code, F#, Programming

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.