12

Why is f <$> g <$> x equivalent to (f . g) <$> x although <$> is not right-associative?

(This kind of equivalence is valid in a popular idiom with plain $, but currently $ is right-associative!)

<*> has the same associativity and precedence as <$>, but behaves differently!

Example:

Prelude Control.Applicative> (show . show) <$> Just 3
Just "\"3\""
Prelude Control.Applicative> show <$> show <$> Just 3
Just "\"3\""
Prelude Control.Applicative> pure show <*> pure show <*> Just 3

<interactive>:12:6:
    Couldn't match type `[Char]' with `a0 -> b0'
    Expected type: (a1 -> String) -> a0 -> b0
      Actual type: (a1 -> String) -> String
    In the first argument of `pure', namely `show'
    In the first argument of `(<*>)', namely `pure show'
    In the first argument of `(<*>)', namely `pure show <*> pure show'
Prelude Control.Applicative> 
Prelude Control.Applicative> :i (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
    -- Defined in `Data.Functor'
infixl 4 <$>
Prelude Control.Applicative> :i (<*>)
class Functor f => Applicative f where
  ...
  (<*>) :: f (a -> b) -> f a -> f b
  ...
    -- Defined in `Control.Applicative'
infixl 4 <*>
Prelude Control.Applicative> 

From the definition of <$>, I would expect show <$> show <$> Just 3 to fail, too.

Community
  • 1
  • 1
imz -- Ivan Zakharyaschev
  • 4,921
  • 6
  • 53
  • 104

1 Answers1

21

Why is f <$> g <$> x equivalent to (f . g) <$> x?

This isn't so much a functor-thing as a Haskell-thing. The reason it works is that functions are functors. Both <$> operators work in different functors!

f <$> g is in fact the same as f . g, so the equivalence you're asking about is rather more trivial than f <$> (g <$> x) ≡ f . g <$> x.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • 1
    Thanks for this smart observation! – imz -- Ivan Zakharyaschev Jun 18 '15 at 09:34
  • Well, I meant bringing the other Functor instance into consideration. Perhaps, "observation" is not a good word for this. – imz -- Ivan Zakharyaschev Jun 18 '15 at 09:49
  • Moral of the story: (<$>) = (.) for the function Functor. – AJF Jun 19 '15 at 20:39
  • 1
    The `(<$>)` function for the function functor composes a function before a function which functions as the functor, whose `Functor` instance has the `(<$>)` function defined as the `(.)` function, whose function is to take a function and yield a function which takes a function and gives a function that functions like both functions composed together. – leftaroundabout Jun 19 '15 at 20:44
  • The same explanation for a code that mysteriously type-checks (not sure whether that code is additionally wrong or still equivalent to what was intended): [`forever putStrLn "Hello, infinity"`](http://stackoverflow.com/q/9753389/94687) – imz -- Ivan Zakharyaschev Jul 07 '15 at 16:55