Consider the following wrapper:
newtype F a = Wrap { unwrap :: Int }
I want to disprove (as an exercise to wrap my head around this interesting post) that there’s a legitimate Functor F instance which allows us to apply functions of Int -> Int type to the actual contents and to ~ignore~ all other functions (i. e. fmap nonIntInt = id).
I believe this should be done with a free theorem for fmap (which I read here):
for given f, g, h and k, such that g . f = k . h: $map g . fmap f = fmap k . $map h, where $map is the natural map for the given constructor.
What defines a natural map? Am I right to assume that it is a simple flip const for F?
As far as I get it: $map f is what we denote as Ff in category theory. Thus, in a categorical sense, we simply want something among the lines of the following diagram to commute:

Yet, I do not know what to put instead of ???s (that is, what functor do we apply to get such a diagram and how do we denote this almost-fmap?).
So, what is a natural map in general, and for F? What is the proper diagram for fmap's free theorem?
Where am I going with this?
Consider:
f = const 42
g = id
h = const ()
k () = 42
It is easy to see that f . g is h . k. And yet, the non-existant fmap will execute only f, not k, giving different results. If my intuition about the naturality is correct, such a proof would work. That's what I am trying to figure out.
@leftaroundabout proposed a simpler piece of proof: fmap show . fmap (+1) alters the contents, unlike fmap $ show . (+1). It is a nice piece of proof, and yet I would still like to work with free theorems as an exercise.
So we are entertaining a function
m :: forall a b . (a->b) -> F a -> F bsuch that (among other things)There are two somewhat related questions here.
fmapdo this?The answer to both questions is "no".
A well-behaved
fmapcan't do this becausefmaphas to obey the axioms ofFunctor. Whether our environment is parametric or not is irrelevant. The axiom ofFunctorsays that for all functionsaandb,fmap (a . b) = fmap a . fmap bmust hold, and this fails fora = showandb = (1 +). Somcannot be a well-behavedfmap.A parametric function can't do this because that is what the parametricity theorem says. When viewing types as relations between terms, related functions take related arguments to related results. It is easy to see that
mfails parametricity, but it is slightly easier to look atm': forall a b. (a -> b) -> (Int -> Int)(the two can be trivially converted to each other).(1 +)is related toshowbecausem'is polymorphic in its argument, so different values of the argument can be related by any relation. Functions are relations, and there exists a function that sends(1 +)toshow. However, the result type ofm'has no type variables, so it corresponds to the constant relation (its values are only related to themselves). Since every value includingm'is related to itself, it follows that all parametric functionsm :: forall a b. (a -> b) -> (Int -> Int)must obeym f = m g, i.e. they must ignore their first argument. Which is intuitively obvious since there is nothing to apply it to.One can in fact deduce the first statement from the second by observing that a well-behaved
fmapmust be parametric. So even if the language allows non-parametricity,fmapcannot make any non-trivial use of it.