haskellfunctorhigher-order-functions

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?


Solution

  • 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