Mark Jones writes:
> ...
> The proposal I have outlined above avoids these problems by allowing the
> programmer to write:
>
> data Date = Date (day::Int) (month::Int) (year::Int)
>
> Of course, programmers can already include definitions of these functions
> in their code, but the fact that the definitions of selectors day, month
> and year are produced automatically means that, should we decide to add
> extra fields to a structure, we don't need to update places where Date is
> used in pattern matches.
Yes please. Some of my programs have environment parameters with about eight
fields. Although I use selector functions to avoid huge pattern matches, even
updating the selector functions themselves on inclusion of extra fields is a
pain.
You might go one further and have reconstructor functions, as used in the
RAISE Specification language. They allow something like:
data Date = Date (day :: Int <-> replace_day)
(month :: Int <-> replace_month)
(year :: Int <-> replace_year)
which defines:
replace_day :: Int -> Date -> Date
replace_day day (Date _ m y) = Date day m y
and so on. I find that I use a lot of these. However:
> OTHER COMMENTS:
> ---------------
> There are several reasons why you might *not* like this proposal:
>
> o You can't use the same name for components of different types.
> The classic examples where both a ColouredPoint and a Point
> have x fields cannot be dealt with like this.
I had been toying with improved type definitions myself and decided that
this objection is the killer. Other languages manage sensible name space
rules which allow different types to have fields with the same name. I did
wonder if Haskell overloading might be used somehow, but I don't really
understand that anyway, so gave up. If Haskell can't cure this problem,
then I am inclined to reject the idea as tending to overcrowd the name
space (I know you don't have to give names to *all* fields, but people
will tend to do all or none).
Nick North