I have a multi-parameter typeclass with a functional dependency:
class Multi a b | a -> b
I also have a simple, non-injective type synonym family:
type family Fam a
I want to write an instance of Multi
that uses Fam
in the second parameter, like this:
instance Multi (Maybe a) (Fam a)
However, this instance is not accepted. GHC complains with the following error message:
error:
• Illegal type synonym family application in instance: Fam a
• In the instance declaration for ‘Multi (Maybe a) (Fam a)’
Fortunately, there is a workaround. I can perform a usual trick for moving a type out of the instance head and into an equality constraint:
instance (b ~ Fam a) => Multi (Maybe a) b
This instance is accepted! However, I got to thinking, and I started to wonder why this transformation could not be applied to all instances of Multi
. After all, doesn’t the functional dependency imply that there can only be one b
per a
, anyway? In this situation, it seems like there is no reason that GHC should reject my first instance.
I found GHC Trac ticket #3485, which describes a similar situation, but that typeclass did not involve a functional dependency, so the ticket was (rightfully) closed as invalid. In my situation, however, I think the functional dependency avoids the problem described in the ticket. Is there anything I’m overlooking, or is this really an oversight/missing feature in GHC?
UndecideableInstances
, so I’m not sure why that would be any different here, either. – Judsona -> b
, but I don't find evidence that(Maybe a) -> (Fam a)
. Is that part of the culprit? – SolangeMaybe a -> a
becauseMaybe
is injective, anda -> Fam a
becauseFam
is a type family. – Mccammon