Re: [Haskell-cafe] Is it possible to get the selector functions when defining a generic class?

I don't know much about this database stuff, but I'm pretty sure you want
to *build* the selector, rather than *extracting* it. You should use the
Generics metadata to get the string for parsing/printing, but aside from
that, you just have the products.
On Nov 23, 2016 10:19 PM, "Chris Kahn"
Sorry if anyone gets this twice; the first copy somehow went to a non-existent Google Groups version of haskell-cafe.
GHC.Generics doesn't offer any built-in support for such things. It *looks* like there *might* be some support in packages built around generics-sop. When you're working directly with GHC.Generics, the notion of a record barely even makes sense. A record is seen as simply a possibly-nested product. For example, ('a','b','c') will look *approximately* like 'a' :*: ('b' :*: 'c'). You're generally not "supposed" to care how large a record you may be dealing with, let alone what field names it has. May I ask what you're actually trying to do? Your specific request sounds peculiarly un-generic.
On Wed, Nov 23, 2016 at 9:52 PM,
wrote: Hey all!
I'm trying to understand what's going on in GHC.Generics and defining a generic class... I understand that there's a `Selector` class and `selName` function that can get the name of a selector, but is there a way to access the selector function itself? The documentation conveniently avoids examples involving records and is otherwise quite barren.
So if I have a data type like...
data Person = Person { name :: String , age :: Int } deriving Generic
instance MyTypeClass Person
I want my generic implementation of MyTypeClass to be able to access each selector function in the record, f :: Person -> String, g :: Person -> Int, etc.
Chris
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Hi Chris, With the addition of type-level metadata to GHC.Generics in GHC 8, it's possible to build a field selector generically. I hacked a rough implementation together a while back [1]. (This would undoubtedly be nicer with generics-sop, but I believe the work to adapt it to support type-level metadata is ongoing.) It's somewhat unsatisfying that GHC has already got a selector function, but we can't get at it generically. Depending on the details of your use case, the HasField class to be introduced as part of the OverloadedRecordFields work [2] might provide an alternative. Hope this helps, Adam [1] https://gist.github.com/adamgundry/2eea6ca04fd6e5b6e76ce9bfee454a6b [2] https://github.com/ghc-proposals/ghc-proposals/pull/6 On 24/11/16 03:28, David Feuer wrote:
I don't know much about this database stuff, but I'm pretty sure you want to *build* the selector, rather than *extracting* it. You should use the Generics metadata to get the string for parsing/printing, but aside from that, you just have the products.
On Nov 23, 2016 10:19 PM, "Chris Kahn"
mailto:chris@kahn.pro> wrote: Aaaand you'll get mine twice since I forgot to reply-all the first time :)
Sure, so in postgresql-simple there are two classes for automatically generating functions that encode/decode database rows, `FromRow` and `ToRow`. In the Hasql library--another postgres library--the encoders and decoders must be written by hand for each user-defined type. I want to write a class that will automatically generate these.
I successfully wrote a `FromRow` class that can generate Hasql's `Row` type, since it's basically identical to what's in postgresql-simple's `FromRow`. But in Hasql the encoder type, Params, is contravariant and encoders are defined like:
personEncoder :: Params Person personEncoder = contramap name (value text) <> contramap age (value int)
The `value text` part can be determined based on the type information, but it's also expecting a matching selector function. I'm at a total loss for how I could generate something like this.
On 11/23/2016 10:06 PM, David Feuer wrote: > Sorry if anyone gets this twice; the first copy somehow went to a > non-existent Google Groups version of haskell-cafe. > > GHC.Generics doesn't offer any built-in support for such things. It > *looks* like there *might* be some support in packages built around > generics-sop. When you're working directly with GHC.Generics, the > notion of a record barely even makes sense. A record is seen as simply > a possibly-nested product. For example, ('a','b','c') will look > *approximately* like 'a' :*: ('b' :*: 'c'). You're generally not > "supposed" to care how large a record you may be dealing with, let > alone what field names it has. May I ask what you're actually trying > to do? Your specific request sounds peculiarly un-generic. > > On Wed, Nov 23, 2016 at 9:52 PM,
mailto:chris@kahn.pro> wrote: >> Hey all! >> >> I'm trying to understand what's going on in GHC.Generics and defining a >> generic class... I understand that there's a `Selector` class and `selName` >> function that can get the name of a selector, but is there a way to access >> the selector function itself? The documentation conveniently avoids examples >> involving records and is otherwise quite barren. >> >> So if I have a data type like... >> >> data Person = Person >> { name :: String >> , age :: Int >> } deriving Generic >> >> instance MyTypeClass Person >> >> I want my generic implementation of MyTypeClass to be able to access each >> selector function in the record, f :: Person -> String, g :: Person -> Int, >> etc. >> >> Chris
-- Adam Gundry, Haskell Consultant Well-Typed LLP, http://www.well-typed.com/
participants (2)
-
Adam Gundry
-
David Feuer