VinylRecords / Vinyl

Extensible Records for Haskell. Pull requests welcome! Come visit us on #vinyl on freenode.
http://hackage.haskell.org/package/vinyl
MIT License
260 stars 49 forks source link

A way to get a Generic instance equivalent to that of plain haskell record? #148

Open YPares opened 3 years ago

YPares commented 3 years ago

Currently, the Generic instance of Rec is oblivious of the functor wrapping the fields. This means the Generic instance it provides cannot be equivalent to that of an equivalent Haskell record.

Would there be a way to have:

newtype RecWithGeneric rs = RecWithGeneric (Rec ElField rs)

type Person1 = RecWithGeneric '["firstname" ::: Text, "lastname" ::: Text]

data Person2 = Person2
  { firstname :: Text
  , lastname :: Text }               

that ensures the Generic instances for Person1 and Person2 can be used instead of one another?

YPares commented 3 years ago

Okay, I hacked something around and managed to do it. It's used in that example: https://github.com/YPares/selda/blob/work-branch/vinyl-example/app/Main.hs#L14

acowley commented 3 years ago

Interesting! Is there anything you'd like to see done in the vinyl package to support this?

YPares commented 3 years ago

@acowley If you'd like, maybe you'd want to upstream my GenRec newtype into vinyl. But as such it's kinda limited. It only supports Rec with the ElField functor. (And ARec, but simply through a brute-force conversion to Rec to reuse the instance for Rec, although it's possible GHC is smart enough to optimize away the whole conversion, I didn't check). Maybe SRec could be given an instance too. Also, any functor should work, as long as you "insert" it in the Generic representation of each field. (I never really checked how Generics behave with HKDs à la barbies)

But the instance of Rep I derive can work for basically any Generic-based library (it works with Aeson too for instance), as it only uses M1, (:*:) and K1. Maybe the same could be done for CoRec, but given a lot of Generic-based libs don't like sum types or hack around them, it's less useful anyway IMHO.