On 11 Oct 2007, at 4:06 pm, Tom Davies basically asked for
something equivalent to Ada's
type T is new Old_T;
which introduces a *distinct* type T that has all the operations and
literals of Old_T. In functional terms, suppose there is a function
f :: ... Old_T ... Old_T ... Old_T ...
then you get a function
f :: ... T ... T ... T ...
where Old_T has been uniformly and consistently replaced by T.
More precisely, this happens to the *built in* operations of the
type; it doesn't automatically apply to user-defined operations.
It's extraordinarily useful in Ada. My standard example is that you
can have a 2D array where row subscripts and column subscripts act in
almost all ways like integers BUT they are incompatible types so you
cannot possibly mix them up.
Haskell's newtype comes close, but not quite close enough.
If I write
newtype Foo = Foo String
I cannot then write
x :: Foo
x = "boojumed"
Similarly, if I write
newtype Row = Row Int
newtype Col = Col Int
I cannot use 1 as a Row or Col value, but must instead write
Row 1 or Col 1.
This *is* a limitation of the Haskell type system, and it *does*
on occasion lead to more long-winded code. But I suspect that it
is not a major problem.
For the specific case of numeric types, it is possible to get
essentially
the Ada result, with the same convenience of use, but not the same
convenience of setup.
newtype Row = Row Int deriving (Eq,Ord,Show)
instance Num Row where
(Row x) + (Row y) = Row (x + y)
(Row x) - (Row y) = Row (x - y)
(Row x) * (Row y) = Row (x * y)
fromInteger i = Row (fromInteger i)
...
instance Integral Row where
...
It isn't trivial, but it's easy to write a little script in the
language of your choice given the type and constructor name.