Or maybe it is enough to float the constraint out, this works:

```
instance Alt ZipList where
(<!>) :: forall a. ZipList a -> ZipList a -> ZipList a
(<!>) = coerce ((<!>) @[] @a)
some :: forall a. Applicative ZipList => ZipList a -> ZipList [a]
some = coerce (some @[] @a)
many :: forall a. Applicative ZipList => ZipList a -> ZipList [a]
many = coerce (some @[] @a)
```

I wanted to bring it to your attention and give it a ticket id, but it's almost too rare to discuss except in hypothetical solutions.

I think it is a rare problem for sure, I bet most won't be bitten by it but I don't see why it can't have a nice solution, or at least a first approximation: deriving the instance `Cls F`

(using `newtype`

or `via`

) via an instance `Cls G`

means they are representationally equal at runtime: `Coercible (Cls F) (Cls G)`

.

That assumes

- That it's fine to have
`Coercible @Constraint`

. Because`Constraint`

is`Type`

in Core. - That such coerce-based instances are actually representationally equal to their 'via instance' in every case.

If I am deriving a functor instance of `ZipList`

via `[]`

then GHC can emit an axiom saying: `Functor ZipList`

is coercible to `Functor []`

. This means anything of the form `Functor ZipList => ..`

can be coerced to `Functor [] => ..`

.

On the other hand `Applicative ZipList => ..`

cannot be coerced to any other constraint (unless another newtype derives `Applicative`

but this time via `ZipList`

) because that instance is not derive via any type.

```
newtype ZipList a = ZipList [a]
deriving newtype Functor -- axiom: Functor ZipList ~R Functor []
instance Applicative ZipList -- no axiom
```

Same deal with `Age`

.

We can now coerce `Semigroup Age => Age -> Age -> Age`

to `Semgroup (Sum Int) => Int -> Int -> Int`

because `Semigroup`

of age is presumed to have the same run-time dictionary as `Sum Int`

but we cannot coerce it to `Semigroup Int => ..`

or `Semigroup (Product Int) => ..`

.

```
newtype Age = Age Int
deriving (Semigroup, Monoid) -- axiom: Semigroup Age ~R Semigroup (Sum Int)
via Sum Int -- axiom: Monoid Age ~R Monoid (Sum Int)
```

Fun fact `(~𝈖) = Coercible`

, `(:~𝈖:) = Coercion`

are valid operators in Haskell.

Take the `Alt`

type class as an example, which is `Alternative`

without the `empty`

method:

```
{-# Language ConstrainedClassMethods #-}
{-# Language DerivingVia #-}
import Control.Applicative
class Functor f => Alt f where
(<!>) :: f a -> f a -> f a
some :: Applicative f => f a -> f [a]
some v = some_v
where many_v = some_v <!> pure []
some_v = (:) <$> v <*> many_v
many :: Applicative f => f a -> f [a]
many v = many_v
where many_v = some_v <!> pure []
some_v = (:) <$> v <*> many_v
```

The applicative constraints on the methods means we cannot derive `Alt`

.

If we try to derive it (say via `[]`

) GHC fails to coerce between `Applicative []`

and `Applicative List`

.

```
instance Alt [] where
(<!>) = (<>)
newtype List a = List [a]
-- • Couldn't match type ‘[]’ with ‘List’
-- arising from the coercion of the method ‘many’
-- from type ‘forall a. Applicative [] => [a] -> [[a]]’
-- to type ‘forall a. Applicative List => List a -> List [a]’
-- • When deriving the instance for (Alt List)
--
-- .. same for ‘some’
deriving (Functor, Applicative, Alt)
via []
```

GHC can make use of the provenence of the `Applicative`

instance: we know that that `Applicative List`

was derived via `Applicative []`

using `coerce`

-based deriving (either `newtype`

, `via`

) and so the dictionaries can be considered `Coercible`

(?). If not I'm curious if this fails.¹

This is not the first time I want this (I forgot in what context though), let me know if it's sensible/useful.

¹ Instead of coercing method-by-method could `coerce`

-based deriving coerce the whole dictionary?

Parser change. Allow currying the context of a typeclass or instance. In keeping with Haskell's pervasive currying.

```
class (Functor t, Foldable t) => Traversable t where
..
instance (cls ~=> Typeable, cls ~=> Eq) => Eq (Dyn cls) where
..
instance ( FunctorOf src tgt1 f1
, FunctorOf src tgt2 f2
)
=> FunctorOf src (tgt1 × tgt2) (f1 &&& f2) where
..
class (cls a, cls1 a) => (cls & cls1) a
instance (cls a, cls1 a) => (cls & cls1) a
```

=

```
class Functor t => Foldable t => Traversable t where
..
instance cls ~=> Typeable
=> cls ~=> Eq
=> Eq (Dyn cls)
where
..
instance FunctorOf src tgt1 f1
=> FunctorOf src tgt2 f2
=> FunctorOf src (tgt1 × tgt2) (f1 &&& f2)
where
..
class cls a => cls1 a => (cls & cls1) a
instance cls a => cls1 a => (cls & cls1) a
```

Following normal constraints where this is equivalent,

```
f :: (Eq a, Ord a) => ..
f :: Eq a => Ord a => ..
```

That should work in general and not on the case of Opaque, it may be complicated. If a stock constraint is required more once, locally as you showed, I would want the the instance to be shared

It will work the same as if you used (standalone) stock deriving, with an opaque datatype, this would fail

```
deriving stock
instance Read Opaque
```

Then this should fail as well

```
deriving
via Stock Opaque
instance Read Opaque
```

This opens the possibility that GHC provide more powerful newtypes, that capture not only concrete instances but rules. Just off the top of my head: the `Ap`

modifier lifts an algebra (any "traversable F-algebra" or so I'm told)

```
type Flat :: Type -> Constraint
class Flat a where
zero :: a
one :: a -> a
two :: a -> a -> a
three :: a -> a -> a -> a
instance (Applicative f, Flat a) => Flat (Ap f a) where
zero :: Ap f a
zero = liftA0 zero
one :: Ap f a -> Ap f a
one = liftA one
two :: Ap f a -> Ap f a -> Ap f a
two = liftA2 two
three :: Ap f a -> Ap f a -> Ap f a -> Ap f a
three = liftA3 three
```

This is a pretty simple pattern, but we cannot write such a meta-rule generically

```
instance (Applicative f, cls a) => cls (Ap f a) where
op0 = liftA0 op0
op0' = liftA0 op0'
op1 = liftA op1
op2 = liftA2 op2
op2' = liftA2 op2'
```

This is where we can introduce meta-modifiers

```
-- Merry Christmas
type Stocking :: (k -> Type) -> (k -> Type)
newtype Stocking f a = Stocking (f a)
type Stocking1 :: (k -> k1 -> Type) -> (k -> k1 -> Type)
newtype Stocking1 hof f a = Stocking1 (hof f a)
```

with a virtual `Stocking Ap`

instances that automatically define a lifting for any valid algebra

```
-- generated by GHC
instance (Applicative f, Flat a) => Flat (Stocking1 Ap f a) where
zero :: Stocking Ap f a
zero = liftA0 zero
one :: Stocking Ap f a -> Stocking Ap f a
one = liftA one
two :: Stocking Ap f a -> Stocking Ap f a -> Stocking Ap f a
two = liftA2 two
three :: Stocking Ap f a -> Stocking Ap f a -> Stocking Ap f a -> Stocking Ap f a
three = liftA3 three
```

I propose two newtypes in base to replace and generalize the `stock`

deriving strategy

```
type Stock :: Type -> Type
newtype Stock a = Stock a
type Stock1 :: (k -> Type) -> (k -> Type)
newtype Stock1 f a = Stock1 (f a)
```

with magical compiler instances every time `deriving stock Cls`

works then the instance for `Cls (Stock a)`

or `Cls (Stock1 f)`

should be generated, depending on the kind of `Cls`

's argument. The purpose is to simplify deriving (Haskell Proposal: Simplify Deriving) and to make stock deriving first-class. I think we can soon derive `Traversable`

:) so I will include it

```
type Medal :: Type
data Medal = Gold | Silver | Bronze
deriving (Eq, Ord)
via Stock Medal
type List :: Type
data List a = Nil | Cons a (List a)
deriving (Functor, Foldable, Traversable)
via Stock1 List
```

Them being "first-class" means they are now types like any other modifier and can be combined into more complicated behaviours, `Down`

reverses the stock instance and `Reverse`

reverses the order of processing to be right-to-left.

```
type Medal :: Type
data Medal = Bronze | Silver | Gold
deriving (Eq, Ord)
via Down (Stock Medal)
type Snoc :: Type
data Snoc a = Nil | Snoc (Snoc a) a
deriving (Functor, Foldable, Traversable)
via Reverse (Stock1 Snoc)
```

@sgraf812 The pattern synonym is present in the code, just uncomment it. This was before it was added to `Type.Reflection`

```
type TypeableInstance :: forall k. k -> Type
data TypeableInstance a where
TypeableInstance :: Typeable a => TypeableInstance a
typeableInstance :: forall (k :: Type) (a :: k). TypeRep a -> TypeableInstance a
typeableInstance rep = withTypeable rep TypeableInstance
pattern TypeRep :: forall (k :: Type) (a :: k). () => Typeable a => TypeRep a
pattern TypeRep <- (typeableInstance -> TypeableInstance)
where TypeRep = typeRep
```

@awpr The argument for `Wrapped`

is largely the same as for `Generically`

, it prevents the proliferation of newtype names, with a single place to attach instances: the mysteriously named `Co`

being `Wrapped1 Representable`

.

At a first glance the relationship between typeclass and such newtype wrappers isn't always clear. This would not replace `Alt`

with `Wrapped Alternative`

since the kinds don't match (edit: that would be `Wrapped1`

, never mind) and instances are not always determined by a single type class like idiomatic lifting `Ap`

which relies on the base class and `Applicative`

. I may be overthinking it at this point.

You can create a ticket for this or garner more feedback from reddit or the mailing list.

@awpr I like the library, it can be implemented separately though. As a type family mapping `Wrapped{,1} Generic{,1} = Generically{,1}`

no?

And if you name it `Ally`

you can write

```
via Generic `Ally` T
via Foldable `Ally` T
```

Mm maybe not

@mpickering I modified it and added commented-out code, if you uncomment it it should work on 8.10. Actually I don't know how to build ghc optimized..

This is what I was trying to implement:

It allows writing `GHC.Generic`

definitions naturally using pattern matching and not type classes, it's very lightweight and relies on `Type.Reflection`

entirely.

```
gput :: AllCls Binary rep => TypeRep rep -> rep () -> Put
gput IsV1 _ = mempty
gput IsU1 _ = mempty
gput IsK1 (K1 a) = put a
gput (IsM1 f) (M1 as) = gput f as
gput (IsProd f g) (as :*: bs) = gput f as <> gput g bs
```

This code takes around 48s to compile on ghc 8.10 and around 12s to compile on ghc 9.3.20210709. Maybe this is something you are interested in taking a closer look at. The example relies heavily on `Type.Reflection`

, I have not minimized it but I am attempting to define generic implementations without using an adhoc typeclass definition.

```
{-# Language FlexibleContexts #-}
{-# Language GADTs #-}
{-# Language PatternSynonyms #-}
{-# Language PolyKinds #-}
{-# Language ScopedTypeVariables #-}
{-# Language StandaloneKindSignatures #-}
{-# Language TypeApplications #-}
{-# Language TypeOperators #-}
{-# Language ViewPatterns #-}
import qualified GHC.Generics as GHC
import GHC.Generics hiding (Constructor, S)
import Type.Reflection
import Data.Kind
is :: forall a b. Typeable a => TypeRep b -> Maybe (a :~~: b)
is = eqTypeRep (typeRep @a)
gcountFields :: forall f a. Typeable @(Type -> Type) f => f a -> Int
gcountFields as
| (is @(V1 @Type) -> Just HRefl) <- typeRep @f
= 0
| (is @(U1 @Type) -> Just HRefl) <- typeRep @f
= 1
| k1 `App` TypeRep `App` TypeRep <- typeRep @f
, (is @(K1 @Type) -> Just HRefl) <- k1
= 1
| m1 `App` i `App` c `App` TypeRep <- typeRep @f
, (is @(M1 @Type) -> Just HRefl) <- m1
, M1 a <- as
= gcountFields a
| or `App` TypeRep `App` TypeRep <- typeRep @f
, (is @((:+:) @Type) -> Just HRefl) <- or
= case as of
L1 a -> gcountFields a
R1 a -> gcountFields a
| and `App` TypeRep `App` TypeRep <- typeRep @f
, (is @((:*:) @Type) -> Just HRefl) <- and
, a :*: b <- as
= gcountFields a + gcountFields b
countFields :: Generic a => Typeable (Rep a) => a -> Int
countFields = gcountFields . from
{-
-- Uncomment for versions before TypeRep was added to base
type TypeableInstance :: forall k. k -> Type
data TypeableInstance :: forall k. k -> Type where
TypeableInstance :: Typeable a => TypeableInstance a
typeableInstance :: forall (k :: Type) (a :: k). TypeRep a -> TypeableInstance a
typeableInstance rep = withTypeable rep TypeableInstance
pattern TypeRep :: forall (k :: Type) (a :: k). () => Typeable a => TypeRep a
pattern TypeRep <- (typeableInstance -> TypeableInstance)
where TypeRep = typeRep
-}
```

**Icelandjack**
(b6998807)
*
at
09 Jul 14:56
*

Add Generically (generic Semigroup, Monoid instances) and Generical...

*
... and
16 more commits
*

I just rebased it

**Icelandjack**
(a4e0039c)
*
at
09 Jul 11:26
*

Add Generically (generic Semigroup, Monoid instances) and Generical...

*
... and
127 more commits
*

`Divides`

can be implemented in terms of `Gcd`

, but I don't have an opinion either way

```
type Divides :: Nat -> Nat -> Nat
type Divides n m = n ~ Gcd n m
```

Can we push on with this change?

Fixed

**Icelandjack**
(cd923287)
*
at
10 Jun 05:41
*

DerivingVia for Hsc instances. GND for NonDetFastString and Lexical...

*
... and
8 more commits
*