Home > Net >  How to understand functor in \g x -> fmap ($) g x
How to understand functor in \g x -> fmap ($) g x

Time:11-18

I am a beginner to Haskell. I know that the function fmap takes two arguments ((a->b) -> f a ->) and returns a functor (f b), but I cannot understand the following lambda expression

*Main> :t \g x -> fmap ($) g x
\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b

where is the functor?

Btw, I have tried several similar expression with different brackets, which give different results:

*Main> :t \g x -> fmap ($) (g x)
\g x -> fmap ($) (g x) :: Functor f => (t -> f (a -> b)) -> t -> f (a -> b)

*Main> :t \g x -> fmap $ g x
\g x -> fmap $ g x :: Functor f => (t -> a -> b) -> t -> f a -> f b

I don't understand this.

CodePudding user response:

From

\g x -> fmap ($) g x :: (t -> a -> b) -> t -> a -> b

we have

g            :: t -> a -> b
x            :: t
fmap ($) g   :: t -> a -> b
fmap ($) g x :: a -> b

To find the functor, it suffices to write the type of g as the type-level application F X for some F and X.

We have

t -> a -> b    =    (->) t (a -> b)

hence, F = (->) t and X = (a -> b).

Therefore, the fmap call works in the (->) t functor. We need to think to t -> a -> b as a value of type a -> b "wrapped" under the functor (->) t.

Now, we have

($) :: (a->b) -> a -> b
-- which means
($) :: (a->b) -> (a -> b)

g   :: F (a->b)
fmap ($) :: F (a->b) -> F (a->b)
fmap ($) g :: F (a->b)
-- i.e.
fmap ($) g :: t -> (a->b)

CodePudding user response:

First, we have, as you said,

fmap :: Functor f 
     => (  a    ->   b   ) -> f a -> f b
($)  ::  (t->s) -> t -> s
g    ::                       f a
     ~                        f (t->s)
-----------------------------------------   a ~ (t->s) ~ b
fmap ($) g ::                        f b
           ~                         f (t->s)

and then this is applied to an x... but only functions get applied to arguments:

fmap ($) g :: Functor f        => f    (t->s)
           ~  Functor ((->) c) => c -> (t->s)
           x                   :: c
----------------------------------------------   f ~ ((->) c)
fmap ($) g x                   ::      (t->s)

and indeed ((->) c) is a functor. So the application to an x is what selects a specific Functor type, the Functor of functions.

Putting it all together,

--                         g             x
\g x -> fmap ($) g x :: (c -> (t->s)) -> c -> (t->s)

-- compare with
        fmap ($)     ::  f    (t->s)  -> f    (t->s)   -- Functor (f ~ ((->) c)
        fmap id      ::  f    q       -> f    q
        id           ::  r            -> r

Indeed ($) is just a more specialized id, and fmap id === id, by the Functor Laws. The type just gets more specialized because of all the extra arguments / instantiations giving more context to it.

  • Related