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.