Reputation: 48662
These two rules about Functor
s are fairly well-known:
Functor
if the type parameter appears contravariantlyFunctor
instanceBut 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?
Upvotes: 7
Views: 144
Reputation: 48611
Absolutely. Suppose you have
newtype Foo a = Foo Bool
mkFoo = Foo True
Here are its two Functor
instances:
instance Functor Foo where
fmap _ (Foo x) = Foo x
instance Functor Foo where
fmap _ !_ = mkFoo
Upvotes: 3