Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can smart-constructor types have multiple valid Functor instances?

These two rules about Functors are fairly well-known:

  1. You can't make a Functor if the type parameter appears contravariantly
  2. 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 HLists 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?

like image 916
Joseph Sible-Reinstate Monica Avatar asked May 14 '20 22:05

Joseph Sible-Reinstate Monica


Video Answer


1 Answers

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
like image 143
dfeuer Avatar answered Sep 30 '22 05:09

dfeuer