Stephane Rolland
Stephane Rolland

Reputation: 39896

Functorial structure of functions

I'm having difficulties understanding the functorial structure of functions.

I think I have a clue with ghci:

Prelude> :t (->)
(->) :: * -> * -> *

So if feeded a type, applying on it (->) will have desired kind * -> *, which is ok for Functor definition.

However I cannot find the reason why we can write:

Prelude> let test = fmap (+1) (+1)
Prelude> :t test
test :: Integer -> Integer

What is the functor instance used when dealing with (->) ? What does it look like ?

What does it do ? I mean I don't understand the effect of the first (+1) onto the second function (+1)

Upvotes: 3

Views: 142

Answers (1)

Random Dev
Random Dev

Reputation: 52270

Your reasoning is absolutely right - now you just have to think what this means for your functor instance.

Usually your functors f fmap type is like this:

fmap :: (a -> b) -> (f a -> f b)

but now you have (->) r (you can think of this as r -> *) instead of f

so if you just fill this in you get:

fmap :: (a -> b) -> ((r -> a) -> (r -> b))

and if you read this carefully this means that given a function g :: a -> b fmap g will be able to transform a function f :: r -> a into a function fmap g f :: r -> b


The functor instance for (->) r looks like this:

instance Functor ((->) r) where
   fmap g f = \ r -> g (f r) -- = g . f

it's a bit strange when you see it the first time but it's basically just function composition (or if you like the source-type is constant and you fmap the result of applying your function)

so in the example you get:

fmap (+1) (+1)
{ def. (+1) }
= fmap (+1) (\r -> r+1)
{ fmap here }
= \r -> (+1) (r+1)
{ definition (+1) }
= \r -> (\a -> a+1) (r+1)
{ lambda application }
= \r -> (r+1) + 1
= (+1) . (+1) -- if you like
{ which is the same as }
= \r -> r+2
= (+2) -- if you like

so you get a function that adds 2 to the result.

But you will probably see more if you look at

fmap (*2) (+1)
{ def. (+1) }
= fmap (*2) (\r -> r+1)
{ fmap here }
= \r -> (*2) (r+1)
{ definition (*2) }
= \r -> (\a -> a*2) (r+1)
{ lambda application }
= \r -> (r+1) * 2
= \r -> r*2+2
= (*2) . (+1) -- if you like

so you see

fmap g f = g . f

by the way you can have a look at the Implementation itself if you click on the source link in the hackage doc

there it's just

instance Functor ((->) r) where
    fmap = (.)

Upvotes: 4

Related Questions