ekmett / adjunctions

Simple adjunctions
http://hackage.haskell.org/package/adjunctions
Other
44 stars 27 forks source link

[RFC] Add Data.Functor.Rep.TH #8

Open bgamari opened 10 years ago

bgamari commented 10 years ago

This is a first cut at deriving Rep instances with Template Haskell. Does this interface look sane?

bgamari commented 10 years ago

I should add that @ekmett has suggested using generics for this but I'm a bit too dense to see a way of doing this that provides the same ease of use and safety as the Template Haskell option.

bgamari commented 10 years ago

One open question surrounding this patch is what set of instances the representation type should be equipped with. Currently this set includes Typeable which is a bit unfortunate as it requires -XDeriveDataTypeable.

ekmett commented 10 years ago

I may take a bit to merge this one, but I'm sold on the general idea.

sjoerdvisscher commented 10 years ago

I would expect the generics based code to look like this:

import qualified GHC.Generics as Gen

class Distributive f => Representable f where
  type Rep f :: *
  type Rep f = Rep (Gen.Rep1 f)

  tabulate :: (Rep f -> a) -> f a
  default tabulate :: (Gen.Generic1 f, Rep (Gen.Rep1 f) ~ Rep f, Representable (Gen.Rep1 f)) => (Rep f -> a) -> f a
  tabulate = Gen.to1 . tabulate

  index    :: f a -> Rep f -> a
  default index :: (Gen.Generic1 f, Rep (Gen.Rep1 f) ~ Rep f, Representable (Gen.Rep1 f)) => f a -> Rep f -> a
  index = index . Gen.from1

and also a lot of instances for Functor, Distributive and Representable for all the GHC.Generics data types except V1 and :+:.

And then you can do

instance Representable A

instead of

deriveRep 'A

But I'd first start with derving instances for Distributive actually. Although Distributive has the problem that all methods already have a default implementation, so when you replace one method with a generic implementation, anyone who doesn't use generics would have to implement that one and would no longer be able to choose between implementing distribute or collect.

ekmett commented 10 years ago

I'm open to including both GHC.Generics and template-haskell based versions as the former is 'zero touch' for the easy cases and the latter yields nicer representations.

On Thu, Apr 3, 2014 at 5:26 PM, Sjoerd Visscher notifications@github.comwrote:

I would expect the generics based code to look like this:

import qualified GHC.Generics as Gen

class Distributive f => Representable f where type Rep f :: * type Rep f = Rep (Gen.Rep1 f)

tabulate :: (Rep f -> a) -> f a default tabulate :: (Gen.Generic1 f, Rep (Gen.Rep1 f) ~ Rep f, Representable (Gen.Rep1 f)) => (Rep f -> a) -> f a tabulate = Gen.to1 . tabulate

index :: f a -> Rep f -> a default index :: (Gen.Generic1 f, Rep (Gen.Rep1 f) ~ Rep f, Representable (Gen.Rep1 f)) => f a -> Rep f -> a index = index . Gen.from1

and also a lot of instances for Functor, Distributive and Representablefor all the GHC.Generics data types except V1 and :+:.

And then you can do

instance Representable A

instead of

deriveRep 'A

But I'd first start with derving instances for Distributive actually. Although Distributive has the problem that all methods already have a default implementation, so when you replace one method with a generic implementation, anyone who doesn't use generics would have to implement that one and would no longer be able to choose between implementing distribute or collect.

— Reply to this email directly or view it on GitHubhttps://github.com/ekmett/adjunctions/pull/8#issuecomment-39507018 .

bgamari commented 10 years ago

@sjoerdvisscher, regarding Distributive you might want to have a look at https://github.com/ekmett/distributive/pull/4. It was only after working through this that I realized how one might derive Representable from Generic as you documented. This is now on my to-do list for an idle weekend but it could be a while until such a weekend appears.

bgamari commented 9 years ago

@sjoerdvisscher the trouble with this Generic approach is that you require Representable (Rep1 f) which isn't possible as Rep1 f is not a functor as would be required by the Distributive f class bound. Perhaps you meant GRepresentable (Rep1 f) here?

bgamari commented 9 years ago

@sjoerdvisscher oh dear, I completely overlooked your mention of introducing Functor instances for the generic types. Forget about the above.