Polymorphic record update

Niklas Broberg niklas.broberg at gmail.com
Tue Jan 24 03:31:21 EST 2006

On 1/23/06, Henrik Nilsson <nhn at cs.nott.ac.uk> wrote:

[snip lots of good stuff]

This suggestion would go a long way to alleviate the burden of
boiler-plate coding. It is a conservative extension, and it is
intuitive at that. Indeed I believe I have written code with the
suggested update mechanism many times without thinking on the type
mismatch (and been beaten on my fingers by the compiler of course).

> But we'd rather not have to write such functions by hand, just as
> we'd rather not write update functions by hand. Maybe the record
> update syntax could be extended so that the function that gets
> generated behind the scenes only includes constructors that
> does NOT mention a particular field. For example, the field
> name(s) that must not occur could be prefixed by "~" which suggests
> negation in some settings. It does not have this connotation in Haskell,
> but at least "~" is already a special symbol. We could then write:
>     foo :: T a -> T Int
>     foo x@(C1 {}) = x {f1 = 1}
>     foo x@(C2 {}) = x {f1 = 2}
>     foo x         = x {~f1}
> Now the code for "foo" only has to be changed if new constructors
> having a field "f1" are added.
> Of course, it should be possible to combine this with the normal
> record update syntax. E.g.
>     foo :: T a -> T Int
>     foo x@(C1 {}) = x {f1 = 1}
>     foo x@(C2 {}) = x {f1 = 2}
>     foo x         = x {~f1, f2 = f2 x + 1}

Is this really necessary? Adding '~' seems less intuitive to me than
just writing

     foo :: T a -> T Int
     foo x@(C1 {}) = x {f1 = 1}
     foo x@(C2 {}) = x {f1 = 2}
     foo x         = x

     foo x = x {f2 = f2 x + 1}

for the last example. From an implementor's point of view, if we
expect the proper coercions to be inferred by the type checker it
would still have to check that there are indeed no more fields than
other than 'f1' that mention the parameter 'a', and also that there
are no more constructors that mention 'f1'. Wouldn't it be just as
simple to assert that for all the fields that mention 'a', none of
these appear in any of the remaining constructors?

On the other hand pattern matching would certainly be more expressive
if '~' is added, so perhaps adding it has merit of its own. If we

     foo :: T a -> T Int
     foo x@(C1 {}) = x {f1 = 1}
     foo x@(C2 {}) = x {f1 = 2}
     foo x         = x {~f1}

there could still be more constructors in T a that do mention the 'f1'
field, but there is no matching clause for them in the definition of
'foo'. But I would see that as a second separate proposal, e.g. a
Proposal for Negation in Record Pattern Matching. Sure it would fit
very well with the Polymorphic record update discussed here, but I
would think they should be treated separately.


More information about the Haskell-prime mailing list