These two rules about Functor
s are fairly well-known:
- You can't make a
Functor
if the type parameter appears contravariantly - Any type has at most one valid
Functor
instance
But if you cheat slightly, you can break the first rule. Take the Hughes list, for example:
data HList a = UnsafeHList ([a] -> [a])
pattern HList a <- UnsafeHList (($ []) -> a)
where HList a = UnsafeHList (a ++)
instance Functor HList where
fmap f (HList a) = HList (map f a)
-- instances necessary to make HList useful, but irrelevant to this example, have been omitted
As long as you make the assumption that all HList
s will be made through the smart constructor, that Functor
instance is lawful, even though a
appears contravariantly.
My question: can you use a similar technique to break the second rule? Are there any types that have two different valid Functor
instances if you assume that they'll always be made through smart constructors?
newtype HList a = HList (forall b. (a -> b) -> [b] -> [b])
– Pelag