Open Icelandjack opened 2 years ago
I haven't tested it much, and the name is up for grabs
I agree that the Generic1
-based default is rather clunky to use, to the point where I'd be surprised if anyone was actually using it in practice. That default predates DerivingVia
, and if I were to redesign this part of adjunctions
from scratch, I'd reach for a solution similar to yours. That is to say: let's add something like this!
One minor hiccup: although Generically1
now exists in base
, it would require an extremely recent version of base
to use, and we'd like to have a wider GHC support window in adjunctions
. For this reason, I think we should define our own version of Generically1
in adjunctions
, but with a more specific name.
It makes sense to add a newtype separate from base. Generically1
doesn't have a configuration parameter anyway.
An 'off-topic' question is how parameters should be handled and what your thoughts are on that. Should they be defined per library or defined in base where there is one common name like Generically
? This comes up in this library but others like json and Arbitrary
.
generic-random offers a suitable candidate for Arbitrary (Generically a)
where everything is generated with uniform probability but it also has newtypes to tinker and customize the instances, is it worth fitting this into a singular mold?
deriving Arbitrary via GenericArbitrary '[2, 3, 5] X
deriving Arbitrary via GenericArbitrary '[1, 2, 3] `AndShrinking` X
deriving Arbitrary via GenericArbitraryRec '[2, 3, 5] X
deriving Arbitrary via GenericArbitraryG CustomGens '[2, 3, 5] X
I'm not sure what you mean by "parameters" in the context of adjunctions
. I was imagining that the only thing you'd need to specify is the type to use as the Rep
instance. Are there ever situations where you would want to configure things more than that?
For this ticket we just need to add a single newtype that specifies the Rep
type.
Obviously that only works when the generic representation lines up: eventually users will want to specify more intricate isomorphisms. That's not important now though.
I was wondering if all libraries should provide a custom newtype or if GenericallyAs :: Type -> config -> Type
belongs in base or not
A similar issue affects Co
as well.
For example, we can only derive Comonad
when Rep
is a monoid
instance (Representable f, Monoid (Rep f)) => Comonad (Co f)
We might wish to have Rep Pair = Bool
but get the Comonad
behaviour via All
or Any
:
deriving Comonad
via CoOf Any Pair
For now, my inclination is to do whatever is simplest to specify, and the API you propose in https://github.com/ekmett/adjunctions/issues/71#issue-1177516196 fits the bill. My opinion is that the design space for type-level configurations is murky enough that it's not worth pursuing here—at least, not unless more users specifically ask for one point in the design space.
The generic
Rep
definition is too robotic, if I deriveRepresentable Count
I most likely don't want to index byRep Count = Either () (Either () ())
but by something likedata Move = Rock | Paper | Scissors
!I have implemented a via type that allows us to derive
Representable
with a specifiedRep
: