Understand Functions Are Functors¶
Functions are functors is a basic idea in funcitonal programming. However, the (->) r
formats of functions are confusing and misleading, What's worse, affected by imperative language features, there was an misunderstanding about how the original structure is hold by a functor. To be more concrete, this blog talks about the question: why result of fmap (*2) (+100) 1
is 202
, not 102
?
It's not an introduction of functors itself so I won't be verbose here. However, it's still necessary to know it:
Tip
The Functor typeclass represents the mathematical functor: a mapping between categories in the context of category theory. In practice a functor represents a type that can be mapped over.
The basic concept of functor could make an analogy to imperative language easily, especially with many real examples:
Those examples show the idea is simple and easy, something holds a value inside it and a function could be applied on the inside value without affecting the outside structure.
It is definitely true. However, if the mind of the outside structure is just a container, like structures in imperative languages, it greatly thwarts to understand functions correctly. Indeed, this is how I wrongly understand the function as a functor.
Functor and Value are Combined Together
Even though fmap
says it could apply the value inside it without affecting outside structure, the functor and inside value are coupled together as one.
Hence, the fmap (*2) (+100) 1
should treated (+100) 1
as one, instead of 1 is hold inside the functor (+100)
.
Wrong Understanding
If the value inside a functor is treated separatedly from functor, fmap (*2) (+100) 1
will be calculated as listed below:
This is fully wrong, because it treats them separately. Functor f
and value type a is combined together f a
, a functor could be represented as ( -> r)
. Hence, ( -> r) a = ( a->r )
, the combination of a function functor is the r
finally, which refers to the result after function call instead of the value inside it(which is input).
Correct Understanding
The confusion could be waived when we use different types in function signatures. If a string append function is applied on the functor which converts from Int to String, it's intuitive that we need to convert the Int
to String
first, and then concat them together.