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

Andres Loeh mail at andres-loeh.de
Thu Nov 24 12:12:34 UTC 2016


Hi Chris.

Here's a proof-of-concept implementation using generics-sop:

https://gist.github.com/kosmikus/83a644fcaa620b5f5505d48540a5f155

It's entirely untested, but it should in principle work, and it should
demonstrate how you can do the contramap/selector stuff generically,
so perhaps it helps.

Cheers,
  Andres


On Thu, Nov 24, 2016 at 4:17 AM, Chris Kahn <chris at 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,  <chris at 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
>>>
>>> _______________________________________________
>>> 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.
> _______________________________________________
> 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.


More information about the Haskell-Cafe mailing list