Why not allow empty record updates?
wren ng thornton
wren at freegeek.org
Wed Nov 16 01:18:21 CET 2011
On 11/15/11 12:33 PM, Yitzchak Gale wrote:
> Simon Peyton-Jones wrote:
>>>>> Trouble is, what type does this have?
>>>>> f x = x {}
>
> Malcolm Wallace wrote:
>>>> f :: a -> a
>
> Ian Lynagh wrote:
>>> That wouldn't help the original poster, as it is incompatible with
>>> f :: Foo Clean -> Foo Dirty
>
> Only because in that expression the type of x is not known.
>
>>>>> ...the whole feature of type-changing update is (as you know)
>>>>> a bit obscure and not widely used, so it'd be adding
>>>>> complexity to an already-dark corner.
>
> To me, at least, that is surprising. The report implies that
> record updates are just sugar for the given case expression.
> Whether or not it changes a type parameter seems
> unimportant.
>
> In fact, I would even advocate adding a line of explanation
> in the Report that this is a convenient way of copying
> a value from an ADT to itself with a different type
> as its parameter. I agree with Malcolm that this is
> analogous to using empty record syntax in a pattern
> to avoid hard-coding the number of parameter to
> a constructor.
>
> I usually avoid using the combination of type parameters and
> record syntax altogether, mainly because this obvious syntax
> doesn't work. Perhaps that's the reason why type-changing
> update is not widely used.
>
> (Admittedly, I didn't think of Herbert's trick. But doesn't
> that seem like somewhat of an ugly hack?)
>
> Are you hesitant because of implementation difficulty,
> or only because you are worried about the semantics
> being confusing? In my opinion, it's more confusing
> the way it is now.
For what it's worth, I do the exact same thing in the project I've been
working on. The phantom type is a clean/dirty bit even :)
It's an incredibly helpful thing to have for records. Especially for the
context I'm in: I'm generating summary data over gobs of input, but the
input can come incrementally. So long as the core of the summary is
correct, then I don't care about maintaining the cache fields while I'm
just shoveling data in; but I do want to make sure the caches are valid
before I try to get any information out. This is exactly the sort of
type-level hackery which makes Haskell a joy to work in and other
languages such a pain.
So far I've just defined helper functions to adjust the phantom type[1],
each of which is implemented by (\x -> x { foo = foo x }). It's a
horrible hack, but at least it's hidden away in library functions
instead of something I have to look at. The annoying part is that when I
adjust the members of the records, if I remove or rename foo then I have
to fix all those coercion functions too.
[1] set bit to Clean, set bit to Dirty, and unsafe set bit to 'a'.
--
Live well,
~wren
More information about the Glasgow-haskell-users
mailing list