Magic classes for Overloaded Record Fields, overlaps, FunDeps

AntC anthony_clayden at clear.net.nz
Thu Apr 28 02:03:30 UTC 2016


> Adam Gundry <adam <at> well-typed.com> writes:
> ...
> 
> P.S. If you have any thoughts on the interaction between ORF and
> encodings of anonymous records, I'd be interested to hear them.

Are you sure you want to open up that question? ;-)
Nikita's record library has certainly given food for thought.

Before we start into anonymous records,
I think we should figure out the path that gets to
extensible records, truncatable records, mergable records,
joinable records, ...
So I'm worried about comments from Nikita
that extensibility is beyond what's possible under that approach.

In considering that, I'm not sure that "anonymous records" are very much
like H98 field-labelled data types.
(Which is to say H98 records are not very much like records ;-)
Trouble is, H98 records have gobbled up so much of the available syntax.

Let's frame the requirement instead as 'labelled tuples'.
Then I'm looking greedily at round-bracket syntax:

    ( name = "Fred", birthday = (day = 28, month = 4, year = 2016) )

I don't know how much Nikita was limited by what's possible
with src-xtns, so I won't bikeshed more about syntax.

Can we use the same ORF mechanisms under the covers
for both labelled tuples and records?
Certainly it would be nice to support intra-conversion routines:

    labelledDT = fromLabels ( name = ... )
    labelledTuple = toLabels labelledDT

I rather think I don't care about the implementation of access
-- that is, whether lenses and which style of lens --
providing it just works. (And doesn't give impenetrable
error messages. That's a bit of a worry with all this higher-kinded
engineering going on in GHC 8.0.
Will ORF's 'Magic Type Classes' have bit-rotted
by the time you get to release them?
Do we call that R.Eisenberg uncertainty? ;-)

Now if you have a label "birthday",
you probably want the field to hold a Date,
not just some arbitrary type 'a'.
And that's what I find unergonomic about the 
label-as-Symbol approach.
(For Nikita's records you give a type for the field alongside the label
 in the record signature.
 But why the need to state the obvious,
 and repeat it for every record that uses "birthday"?)

The labelled "birthday = ..." approach seems
tantalisingly close to data constructors:
    ( Name "Fred", Birthday $ Date 28 4 2016 )

Which takes us (perhaps) to HLIst-style
Type-Indexed Products.
How could they fit with ORF?
Perhaps introduce an implicit label spelled same as the Data Constructor?
Except starting lower case,
otherwise the #name prefix will throw a wobbly.

What gave me a queasy feeling looking at Nikita's Record<n>s
is the alternating labels and data type.
  ::  Record2 "name" String "birthday" Date

I'd rather see explicit pairing of label and data.

newtype Label (l :: Symbol) a = Label a
rec :: Record2 (Label "name" String, Label "birthday" Date)

The newtype should mean zero runtime cost.

I can see a couple of reasons behind Nikita's approach
that might have been getting in the way of that.

Sequencing the labels into alphabetic order.
(Which is probably to implement the second reason.)
Now certainly we want the label position to be arbitrary
in anonymous records. But that's just a bit of representation hiding.
Resequencing them alphabetically means they show
in a probably unmeaningful format.
It also might be getting in the way of extensibility. 
To compare two records with the same labels,
does need the fields in the same seq.
We could do that with:

    labelledTuple `asLabelSeqOf`canonicalLabels

The second reason would be to check for duplicate labels.
Hmm is that essential? YMMV
As far as I can see, duplicate labels within a tuple
are only problematic when you want to get/set
a field by that label.
Your example [1] isn't upset by:
  z4 = getField (proxy# :: Proxy# "bar") (Record3 True False "ok"
           :: Record3 "foo" Bool "foo" Bool "bar" String)

Again if it is a requirement,
it's easy enough to build a smart constructor wrapper
that validates for duplicate labels, á la HList.


Did that answer (any of) your question?

AntC

> 
> [1] https://gist.github.com/adamgundry/7292df8cef62fd6750885be3f5f892e7
> 


More information about the Glasgow-haskell-users mailing list