Don’t execute your dog

Duck typing is how Python asserts type correctness. The name comes from the old truism, which I will refer to as the Duck Assertion:

If it walks like a duck and quacks like a duck, then it's a duck.

Applied to programming, if I’m trying to call quack() on a duck, then any object with a quack() method is judged to be a duck, and thus won’t give me a type error.

The structural typing I’m implementing in Minstrel is very similar to this, only checked at compile time: if I have an interface Duck:

interface Duck 
{
   method quack[] returns Unit;
}

Then another interface is a subtype of Duck if it presents a method compatible with quack[]:

interface BirdBot
{
   method quack[] returns Unit;
   method cheep[] returns Unit;
}

As far as my program is concerned, a BirdBot is a Duck, and can be used in place of it wherever. How marvellous!

Occasionally, however, you find that’s not what you want. Because there are two ways of parsing the Duck Assertion – the nominative:

If it walks (and I have noted that ducks walk) and it quacks (I have noted that ducks quack), then it is a duck.

And the semantic:

If it walks in the manner of a duck, and it quacks in the manner of a duck, then it is a duck.

Duck typing assumes the nominative, but really, what we want is the semantic. Take the examples of a dog and a process:

interface Dog
{
   method run[] returns Unit;
}
interface Process
{
   method run[] returns Unit;
}

This would then allow me to pass my dog to an Executor, and whilst I am all in favour of my dog running free, I am most definitely not in favour of executing it.

How, then, to distinguish between the two cases? In a nominative, hierarchical type system this isn’t a problem: Dog and Process are distinct entities. Not so in a structural system. And there’s no way to distinguish them based on the name or signature of the methods – the thing about homonyms is the name’s a lousy way of differentiating them.

Now, you could argue that a well-constructed domain model simply doesn’t allow you to confuse a Dog and a Process sufficiently for this to become an issue, but there are many domains where domain terms are overloaded in such a way that you have objects with homonymic method signatures in close proximity, and this inadvertent implementation of interfaces can be quite a problem. In English, the way we distinguish homonyms is through context. That’s somewhat harder for a programming language, and it needs a bit of a helping hand.

One solution to this is labels.

Labels

This tries to apply some of the benefits of nominative typing to a structural approach. Basically, an interface is not solely defined by its method signatures: you can attach additional properties to it. This would allow interfaces to be defined as follows:

interface Dog
{
   label Animal;
   method run[] returns Unit;
}
interface Process
{
   label Process;
   method run[] returns Unit;
}
interface Runnable
{
   method run[] returns Unit;
}

Now, you can’t assign a Dog to a Process, because a Process requires two things: a method called run with no parameters and returning Unit, and a label of Process. A Dog has the former, but not the latter. However, you could assign either a Dog or a Process to a Runnable. And it’s entirely non-hierarchical – the property “is an Animal” doesn’t imply anything other than something’s been labelled an Animal.

The main question I’m pondering now is that this does introduce an extra element of complexity, and one that could easily run awry – it may turn out that, with judicious design and appropriate consideration of your domain, that the correct number of labels on interfaces in a well-constructed program is zero. So – for the time being at least – I’m keeping that idea in my back pocket.

But if I do need a solution to the thorny issue of Dog Typing, well, there it is.

Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s