# A curious associativity of the <$> operator Published on The <$> operator in Haskell is an infix synonym for fmap and has the type

(<$>) :: Functor f => (a -> b) -> f a -> f b For example: > negate <$> Just 5
Just (-5)

Like all other operators, <$> has a fixity, which can be infixl, infixr, or infix. The fixity defines how an expression like abs <$> negate <$> Just 5 is parsed. If <$> were defined as infix, then the above expression wouldn’t parse at all, giving an error like

Precedence parsing error
cannot mix ‘<$>’ [infix 4] and ‘<$>’ [infix 4] in the same infix expression

If <$> instead were defined as infixr, then the above expression would parse as abs <$> (negate <$> Just 5) meaning first apply negate to 5 inside Just, and then go inside Just once more and apply abs. However, <$> is defined as infixl, so that the applicative chains like

(+) <$> Just 5 <*> Just 6 would parse correctly. This means that abs <$> negate <$> Just 5 is parsed as (abs <$> negate) <$> Just 5 which is probably not what you meant. Or is it? It turns out that if you paste that expression (either parenthesized or not) into ghci, you’ll get back Just 5 in all cases. This happens because of the following instance defined in the base library: instance Functor ((->) r) where fmap = (.) (Note that (->) r is essentially the Reader monad, so it’s not surprising that it’s a functor.) So the expression (abs <$> negate) <$> Just 5 does make sense and is equivalent to (abs . negate) <$> Just 5

The operators * for which a * (b * c) = (a * b) * c are called associative. Usually associative operators have the type a -> a -> a (either polymorphic of for a specific a), so that both ways to put parentheses typecheck.

The <$> operator is curious because it doesn’t have such a type and yet is associative: f <$> (g <$> h) = {- the definition of <$> -}
fmap f (fmap g h) =
{- the definition of (.) -}
(fmap f . fmap g) h =
{- the functor law -}
fmap (f . g) h =
{- the definition of <$> -} (f . g) <$> h =
{- the Functor instance for (->) r -}
{- g has to be a function for the top expression to typecheck -}
(f <$> g) <$> h