tags:

views:

265

answers:

2

Does D have 'newtype' (as in Haskell).

It's a naive question, as I'm just skimming D, but Google didn't turn up anything useful.

In Haskell this is a way of making different types of the same thing distinct at compile time, but without incurring any runtime performance penalties.

e.g. you could make newtypes (doubles) for metres, seconds and kilograms. This would error at compile time if your program added a quantity in metres to a quantity in seconds, but would be just as fast at runtime as if both were doubles (which they are at runtime).

If D doesn't have something analogous to 'newtype', what are the accepted methods for dealing with dimensioned quantities?

Thanks,

Chris.

+10  A: 

In D1.0 there is typedef, which is the strong typing from a predefined type to a 'newtype.'

D2.0 has removed this and only alias remains (what typedef is in C). There is talk about having a wrapper template that can strongly create a new type.

The issue with typedef was that there were good arguments for making the newtype a sub-type of the predefined type, and also good arguments for making it a super-type.

The semantics of typedef are that the base type is implicitly converted to the newtype, but the newtype is not converted to the base type or other types with the same base type. I am using base type here since:

typedef int Fish;
typedef Fish Cat;
Fish gold = 1;
Cat fluff = gold;

Will fail to compile.

And as of right now, 2.048 DMD still allows the use of typedef (but don't use it).

Having the base type convert to the newtype is useful so you don't have to write

meters = cast(meters) 12.7;
he_the_great
In `typedef X Y`, if `X` is implicitly convertible to or from `Y`, then `typedef` is not very much like Haskell's `newtype`.
Reid Barton
+5  A: 

Funny, as he_the_great mentions, D1 had a strong typedef but noone used it, possibly because it was impossible to customize the exact semantics for each case. Possibly the simplest way to handle this situation, at least for primitive types, is to include a mixin template somewhere in Phobos that allows you to forward all operators but have the boilerplate to do this automatically generated via the mixin. Then you'd just create a wrapper struct and be all set.

dsimcha