I sort of like this but doubt it's worth the breakage it would case. I just wanted to point out (because nobody seems to have mentioned it) that this exists in the invariant package. Is `Endofunctor`

/`endomap`

a better name than `Invariant`

/`invmap`

?

I don't want to derail this further with more bikeshedding, but if people are talking about adding `Profunctor`

to `base`

and making it a superclass of `Arrow`

(which I fully support), should there not be another superclass of `Arrow`

as well, i.e., `Proapplicative`

(also known as `ProductProfunctor`

)? Or does a quantified `Applicative`

superclass constraint negate the need for this (but perhaps we should add that then if so?)? It would be even more work to add it later which is why I bring it up now.

I made a similar (#11210) issue a few months ago and submitted a patch which was accepted. There are some more instances I want to add:

```
instance Num a => Num (Identity a)
instance Real a => Real (Identity a)
instance Integral a => Integral (Identity a)
instance Fractional a => Fractional (Identity a)
instance Floating a => Floating (Identity a)
instance RealFrac a => RealFrac (Identity a)
instance RealFloat a => RealFloat (Identity a)
instance Bits a => Bits (Identity a)
instance FiniteBits a => FiniteBits (Identity a)
instance IsString => IsString (Identity a)
instance Num a => Num (Const a b)
instance Real a => Real (Const a b)
instance Integral a => Integral (Const a b)
instance Fractional a => Fractional (Const a b)
instance Floating a => Floating (Const a b)
instance RealFrac a => RealFrac (Const a b)
instance RealFloat a => RealFloat (Const a b)
instance Bits a => Bits (Const a b)
instance FiniteBits a => FiniteBits (Const a b)
instance IsString => IsString (Const a b)
```

Thanks for the detailed answer!

I understand that. Like I said, I can see why `Eq1`

, etc. are useful in their own right. But the questions I was really asking are:

- Do we care about Haskell 98 compatibility in base?
- If not, could I add an instance e.g.,
`Semigroup (f (g a)) => Semigroup (Compose f g a)`

? There are a bunch of non-Haskell 98 instances I would like to add, especially for`Compose`

. Some of these could be made into Haskell 98-compatible instances with more`Eq1`

-style helper type classes, but some could not.

While I can see how the `Eq1`

, `Ord1`

, `Read1`

and `Show1`

classes could be useful in their own right, is it set in stone that the `Eq`

, `Ord`

, `Read`

and `Show`

instances of the various functors must use them? Why can't the `Eq`

instance for `Compose`

just be `Eq (f (g a)) => Eq (Compose f g a)`

? Do we care about Haskell98 compatibility in `base`

?

I don't have a strong opinion either way for `Eq`

, `Ord`

, `Read`

and `Show`

, but I would slightly prefer instances of the form I have above. What I'm really interested in is the other type classes for which the functors could have instances. Do we need to make a `Semigroup1`

, a `Monoid1`

if we want to make `Compose`

an instance of `Semigroup`

and `Monoid`

? What about a `Storable1`

? Or can we just make an instance `Storable (f (g a)) => Eq (Compose f g a)`

?

I would basically like to make as many of these instances as possible, because I'm working on something at the moment that uses a lot of functors and potentially compositions of functors, but I want to "keep" as many of the instances of my base types as possible.

I'd be happy to do up a patch that made as many of these instances as possible, but I'm wondering would I be expected to make all those extra classes, or could I just make the non-Haskell98 instances? And if so, is there any good reason not to just do the same for `Eq`

, `Ord`

, `Read`

and `Show`

?

Trac field | Value |
---|---|

Differential revisions | - → D1630 |

Sure. I've added one here: https://phabricator.haskell.org/D1626

Could it not be possible to introduce some way of pattern-matching on `GHC.TypeLits`

's `Nat`

s independently of generalised injectivity? Maybe it's a question that would involve a lot of bikeshedding... but surely the compiler ultimately has enough information to prove that `Replicate`

is injective, I just can't destructure type-level `Nat`

s. Could there be a magic built-in pattern synonym `Succ`

for `Nat`

s? Can pattern synonyms work on the type level? I don't really know much about the internals to know how to implement that, but there must be a way.

Like if full generalised injectivity is just around the corner, then maybe we should just wait for that, but from what I've read it sounds like there are still a lot of kinks that need to be worked out first and it might turn out to be too difficult altogether? Right now pretty much every package that does type-level stuff defines its own `Nat`

type, and I'd imagine the lack of the ability to pattern match on `GHC.TypeLits`

's `Nat`

is a big part of the reason for that.

These are also possible:

```
instance Storable a => Storable (Const a b)
instance Storable a => Storable (Identity a)
```

The following instances are all permissible yet are not defined. They can all be derived with `GeneralizedNewtypeDeriving`

. It would be useful for me if they were defined in `base`

. These should probably also go into `base-orphans`

and `transformers`

(for versions of `base`

before `Identity`

was moved there).

```
instance Bounded a => Bounded (Const a b)
instance Enum a => Bounded (Const a b)
instance Ix a => Bounded (Const a b)
instance Semigroup a => Semigroup (Const a b)
instance Bounded a => Bounded (Identity a)
instance Enum a => Bounded (Identity a)
instance Ix a => Bounded (Identity a)
instance Semigroup a => Semigroup (Identity a)
```

Trac field | Value |
---|---|

Version | 7.11 |

Type | FeatureRequest |

TypeOfFailure | OtherFailure |

Priority | normal |

Resolution | Unresolved |

Component | libraries/base |

Test case | |

Differential revisions | |

BlockedBy | |

Related | |

Blocking | |

CC | |

Operating system | |

Architecture |

You're right, they are subtley different. But I can't "pattern-match" on (n + 1) on the LHS with GHC's TypeLits, because + is a type family and not a constructor. If there was some other way I could accomplish this then I would be satisfied with that for now. But obviously if we could get generalised injectivity that we be awesome.

Trac field | Value |
---|---|

Version | 7.10.2 → 7.11 |

The following does not work:

```
{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, UndecidableInstances #-}
import GHC.TypeLits (Nat, type (-))
type family Replicate (n :: Nat) (a :: k) = (r :: [k]) | r -> n where
Replicate 0 a = '[]
Replicate n a = a ': Replicate (n - 1) a
```

It fails to compile with the following error:

```
error:
• Type family equation violates injectivity annotation.
Type variable ‘n’ cannot be inferred from the right-hand side.
In the type family equation:
forall (k :: BOX) (n :: Nat) (a :: k).
Replicate n a = a : Replicate (n - 1) a
• In the equations for closed type family ‘Replicate’
In the type family declaration for ‘Replicate’
Failed, modules loaded: none.
```

However, the following does:

```
{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, UndecidableInstances #-}
data Nat = Zero | Succ Nat
type family Replicate (n :: Nat) (a :: k) = (r :: [k]) | r -> n where
Replicate Zero a = '[]
Replicate (Succ n) a = a ': Replicate n a
```

Sure GHC.TypeLits' built-in Nat type is isomorphic to the one defined above, and thus GHC should be able to infer injectivity for Replicate?

Trac field | Value |
---|---|

Version | 7.10.2 |

Type | Bug |

TypeOfFailure | OtherFailure |

Priority | normal |

Resolution | Unresolved |

Component | Compiler |

Test case | |

Differential revisions | |

BlockedBy | |

Related | |

Blocking | |

CC | |

Operating system | |

Architecture |