Records (was Re: [Haskell] Improvements to GHC)

David Roundy droundy at abridgegame.org
Wed Nov 23 08:22:47 EST 2005


On Tue, Nov 22, 2005 at 02:32:47PM +0000, Rob Ennals wrote:
> Since discussion has returned to records, it might be useful for me to
> post a link to a proposal that I knocked up a while back when this
> topic came up a few years ago:
> 
> http://www.cambridge.intel-research.net/~rennals/records.pdf

Looks pretty nice.

> To go through Dave's issues:
> 
> 1. Field namespaces: solved by using type classes

But these classes are required to be manually specified, right? This avoids
the problem of proliferation of typeclasses if one had one class per field,
but does mean that coordination is necesary in order to avoid namespace
clashes.

As far as I can tell, this means that we'd have issues with

data StupidDouble = StupidDouble { value :: Double }
data StupidInt = StupidInt { value :: Int }

unless we use multiparameter typeclasses or something.  This is a stupid
example (thus the type names), but I think there are real cases where you'd
like to create constructors like this.

> 2. Multi-constructor getters: solved by desugaring to functions
> 3. "Safe" getters for multi-constructor data types: ditto

I think either you misunderstood my meaning by "safe", or I misunderstood
your paper.  I meant that if I write

data FooBar = Foo { foo :: String } | Bar { bar :: String }

there shouldn't be accessors of type

foo :: FooBar -> String
bar :: FooBar -> String

which die when given bad input (e.g. calling (foo $ Bar "bar")).  I'd
rather in this case either not have these functions generated (and require
that I use pattern matching) or have them have type

foo :: FooBar -> Maybe String
bar :: FooBar -> Maybe String

I just don't like bottom.  Perhaps it wouldn't be so bad if we got decent
error messages, but when you call (foo $ Bar "bar") you get no hint as to
where the bug actually is.

> 7. Unordered records: yep (if I understand the problem correctly)

I don't think you understood correctly.  What I'd like (and this is another
one of those David-specific issues--I've never heard anyone else complain
about this) is to be able to create a data type that has no order.  If I
write

data FooBar = FooBar { foo, bar :: String }

I can construct this (either with Haskell 98 or with your proposal, as I
understand it) with either

fb = FooBar { foo = "a", bar = "b" }

or with

fb = FooBar "a" "b"

I'd prefer to at least optionally be able to make the second syntax fail to
compile--which is what I mean by an unordered record.  The same goes for
pattern matching.  This feature is orthogonal to almost all the other
record issues, and really a compiler warning would probably be enough to
satisfy me, although I'd prefer to have this in the language.

The point (in case I've been unclear again) is that I'd like to be able to
later change the definition to

data FooBar = FooBar { foo, bar :: String }

without the possibility of breaking the code.  This is a silly example, and
noone would actually make this change, simply because it would be too hard
to go through the code and verify that all the patterns have been swapped
(and didn't get swapped twice).

It's something that one could implement with code policy, but on the other
hand, you could in principle say the same thing about static typing.
-- 
David Roundy
http://www.darcs.net


More information about the Haskell mailing list