Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is (fmap f) the same as (f .) if f is a function of type a->b?

I am trying to implement a Functor instance of

data ComplicatedA a b
    = Con1 a b
    | Con2 [Maybe (a -> b)]

For Con2, my thought process was the fmap needs to be something like

fmap f (Con2 xs) = Con2 (map f' xs)

then I need to have a list map function f' like

Maybe (a -> x) -> Maybe (a -> y)

Since Maybe is a Functor, I can write f' like

fmap ((a->x) -> (a->y))

In order to get ((a->x) -> (a->y)), I thought I could just do fmap (x->y) which is the same as (fmap f)

So my sulotion was

instance Functor (ComplicatedA a) where
    fmap f (Con1 x y) = Con1 x (f y)
    fmap f (Con2 xs) = Con2 (map (fmap (fmap f)) xs)

However the real solution uses (f .) instead of (fmap f) to get ((a->x) -> (a->y)) from x -> y and it looks like this

instance Functor (ComplicatedA a) where
    fmap f (Con1 a b) = Con1 a (f b)
    fmap f (Con2 l) = Con2 (map (fmap (f .)) l)

I was just wondering what the problem was with my thought process and solution. Is (fmap f) the same as (f .) if f is a function of type a->b?

Thank you in advance.

like image 237
klabe Avatar asked Apr 07 '19 21:04

klabe


People also ask

What does Fmap do Haskell?

fmap is used to apply a function of type (a -> b) to a value of type f a , where f is a functor, to produce a value of type f b . Note that for any type constructor with more than one parameter (e.g., Either ), only the last type parameter can be modified with fmap (e.g., b in `Either a b`).

Is tree a functor?

The Select method first translates the contained Item using the selector function, and then recursively calls itself for each sub-tree in children . This method has the desired signature, and furthermore obeys the functor laws, as you'll see later in the article. Tree<T> is a functor.

What does just mean in Haskell?

It represents "computations that could fail to return a value". Just like with the fmap example, this lets you do a whole bunch of computations without having to explicitly check for errors after each step.


1 Answers

The solutions are indeed equivalent. fmap for the function/reader functor is (.):

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

((->) r is the function type constructor being used with prefix syntax -- (->) r a is the same as r -> a.)

The intuition is that, as you have noted, (.) :: (x -> y) -> (a -> x) -> (a -> y) uses a x -> y function to modify the results of an a -> x function.

like image 133
duplode Avatar answered Oct 16 '22 19:10

duplode