Question

How does <$ = (fmap . const) in Functor even work in Haskell?

I know that the dot (.) operator takes two functions which both take an argument respectively, and the third argument for the second argument.

Its type is (.) :: (b -> c) -> (a -> b) -> a -> c.

For example, take 1 . drop 2 $ [1,2,3,4,5].

But how can (fmap . const) work?

The fmap function needs two arguments, and the const function takes two arguments and then return the first argument.

So logically, the fmap should take the output which is the first argument taken by the const function.

The types of two functions:

fmap :: Functor f => (a -> b) -> f a -> f b
const :: a -> b -> a

The fmap in (fmap . const) 2 (Just 4) should get the output 2 returned by the const function, so it'd not work, but actually it does work.

What happened?

 4  145  4
1 Jan 1970

Solution

 9

The fmap function needs two arguments, and the const function takes two arguments and then return the first argument.

No, every function takes one parameter, and sometimes produces a function as result. fmap :: Functor f => (a -> b) -> (f a -> f b), takes one function, of type a -> b, and then produces a function that maps an f a to an f b.

Now, the same trick is necessary when we work with const :: c -> d -> c, this is short for const :: c -> (d -> c), so again, a function that takes a value, and then produces a function that will map any value to the given value.

So then what is fmap . const? It is short for \x -> fmap (const x). It thus asks for a value x, and then produces an fmap (const x), this thus means that fmap will map any value to x. This thus means that if we work for example with x = 42, and a list [1,4,2,5], we get fmap (const 42) [1,4,2,5], and this thus means that we map any item of the list to 42, so [42, 42, 42, 42].

2024-07-08
willeM_ Van Onsem

Solution

 4

Just unify the types:

fmap         :: Functor f =>      (a -> b) -> (f a -> f b)
const        ::              b -> (a -> b)
fmap . const :: Functor f => b             -> (f a -> f b)

So fmap . const takes x :: b and produces fmap (const x) :: f a -> f b.

In your example,

  (fmap . const) 2 (Just 4)
= ((fmap . const) 2) (Just 4)
= fmap (const 2) (Just 4)
= Just (const 2 4)
= Just 4
2024-07-08
Na&#239;m Favier

Solution

 2

Function composition, ., is defined as:

f . g = \x -> f (g x)

By replacing . with its definition in fmap . const you obtain the equivalent expression:

\x -> fmap (const x)

Similarly, if you replace fmap . const in the expression (fmap . const) 2 with its equivalent, \x -> fmap (const x), you obtain:

(\x -> fmap (const x)) 2

Finally, applying the argument 2 above:

fmap (const 2)
2024-07-08
ロウリン