Lets say I've got the class:
class C a b t where
f :: (a, b) -> (t a, t b)
Now with this definition, I can define instances for say:
(a,b) -> (Maybe a, Maybe b)
(a,b) -> ([a], [b])
But not for (as far as I understand):
(a,b) -> (a,b)
(a,b) -> ((a, a), (b, b))
I could instead change my class definition like so:
type family T a b x
class C a b where
f :: (a, b) -> (T a b a, T a b b)
Which would allow me to do the above, but then I'd only be able to declare one f
for each a
and b
.
Basically I want to be able to pass a type family as t
in the original definition, which is implicitly resolved by the type checker if known. I don't want to just make it f :: (a, b) -> (c, d)
as I want to maintain the invariant that both a
and b
have the same thing done to them, so swap . f
is the same type as f . swap
. I'm thinking I might need injective type families (from GHC 8.0) but I'm not sure. But maybe there's another way?