agrafix / superrecord

Haskell: Supercharged anonymous records
BSD 3-Clause "New" or "Revised" License
83 stars 16 forks source link

Is label sorting necessary? #11

Open vagarenko opened 7 years ago

vagarenko commented 7 years ago

I want to use Superrecord to work with foreign data. I need records Rec '["foo" := Int, "bar" := Float] and Rec '["bar" := Float, "foo" := Int] to be different, because they correspond to different C structs, but I can't even create Rec '["foo" := Int, "bar" := Float] because rcons sorts labels of its result record.

So, why do you need label sorting? Can the library work without it?

agrafix commented 7 years ago

No, the sorting is not strictly needed. We've added it so that you do not need to worry about the order of the fields when constructing something. You can find more on this discussion at the top comment on reddit.

That said, it would be possible to provide an API that does not require sorting. What I've also been thinking about is adding support to add other annotations to fields, like for instance an alternative json key or database field name. If this was given, one could also use that for a mapping to C structs. What do you think? Could you give an example use case you are thinking of?

vagarenko commented 7 years ago

I'm trying to write Storable instance for Rec so

Rec '["foo" := Int, "bar" := Float]

would map to the following C struct:

struct {
  int foo;
  float bar;
}

and

Rec '["bar" := Float, "foo" := Int]

would map to

struct {
  float bar;
  int foo;
}

and I don't see how to do it with key sorting.

agrafix commented 7 years ago

This would be possible with annotations:

Rec '["foo" := Ann (CPos 0) Int, "bar" := Ann (CPos 1) Float]

would be

struct {
  int foo;
  float bar;
}

and

Rec '["foo" := Ann (CPos 1) Int, "bar" := Ann (CPos 0) Float]

would be

struct {
  float bar;
  int foo;
}
crabmusket commented 7 years ago

Could you not expose the old (non-sorted) Rec as OrderedRecord or similar? Then type Record r = Sort (OrderedRecord r)? It seems cleaner than specifying Ann and CPos, though if you're doing to do all sorts of things with annotations then why not!

agrafix commented 7 years ago

This is already the case:

type Record lts = Rec (Sort lts)

and Rec lts is the variant that doesn't care about ordering. The problem are the operations on the record that add or change the fields.

axman6 commented 6 years ago

Is the ability to use == really the best reason for adding the complexity that sorting fields adds? It seems that sorting touches many parts of the API that shouldn't need it, such as appending two Recs. It seems more sensible to me to provide an eqRec function which checks Sort lhs ~ Sort rhs and then indexes into the original records to compare each field. The storable case, as well as things like parsing and writing CSVs are cases I could definitely see myself finding more useful than having the ability to use ==.

agrafix commented 6 years ago

Sorry for dropping the ball on this one, I agree it's not optimal but it's not only due to == - any case where you have explicit type signatures for a specific (closed) record will fail to type check if you create your records without sorting them. I think a better approach here is probably to make an unsorted version, export that and build the sorted version on top of it such that users have a choice what to use.