lift restrictions on records with existential fields, especially in the presence of class constraints
the attached file demos the use of a record with an existential field with a class constraint. it shows several cases where lifting the current restrictions on accessing and updating this field would be both well-defined and useful.
here is the record definition; the dur field is existential, but constrained to be in class NoteDur.
data Note = forall x . NoteDur x => Note {
midiNum :: Int -- 0-255
, vel :: Int -- 0-255
, chan :: Int -- 0-15
, measure :: Integral a => a
, beat :: Int
, subdiv :: RealFrac a => a -- % of beat
, dur :: x
}
here is a walk through of places in the code where the current restrictions are unnecessary and intrusive:
- lines 64-95 -- these functions wouldn't be necessary if record update syntax were enabled for both existential and non-existential fields. i know 6.12 introduces it for non-existentials, but i don't see why it isn't also possible for existential fields (even without a class constraint). lines 33-35 and 60 show how much nicer it is to use regular updater syntax in this case.
- Line 142. The same is true for existential accessors when there is a class constraint -- there's no need to restrict this situation because the accessor can have type:
fieldName :: (SomeClass x) => Record -> x
line 142 shows a case where this would be very nice to have.
- line 100 + 107 -- the foralls could be implicit (maybe offer an extention that would allow them to be implicit)
- lines 134-136 compared to 138-139 show how additional factoring could be achieved if one were allowed to pattern match on the type of an existential with class constraints.
- lines 124-127 show how it would be nice to have existential classes
- lastly, allow curried updater functions:
(rec {field = }) 5
instead of(\x -> (rec {field = x})) 5
Edited by Simon Peyton Jones