Search code examples
haskellfunctorapplicative

x <*> y <$> z in Haskell


I'm trying to understand some Haskell source code, and I encountered this structure some times:

x <*> y <$> z

e.g.

(+) <*> (+1) <$> a

Can somebody explain this structure to me? I get that it translates to fmap a (+ a + 1), but I can't make the connection


Solution

  • Let's start with:

    x <*> y <$> z
    

    Adding parentheses, it becomes:

    (x <*> y) <$> z
    

    Given that (<$>) :: Functor f => (a -> b) -> f a -> f b, we have:

    x <*> y :: a -> b
    z :: Functor f => f a
    

    Given that (<*>) :: Applicative g => g (c -> d) -> g c -> g d, we have:

    x :: Applicative g => g (c -> d)
    y :: Applicative g => g c
    x <*> y :: Applicative g => g d
    

    Combining the last few results, we get:

    g d ~ a -> b
    g ~ (->) a
    d ~ b
    
    x :: a -> c -> b
    y :: a -> c
    x <*> y :: a -> b
    

    Therefore:

    (\x y z -> x <*> y <$> z) :: Functor f => (a -> c -> b) -> (a -> c) -> f a -> f b
    

    Now knowing that (<*>) from the function instance is being used, we can also substitute its definition:

    x <*> y <$> z
    (\r -> x r (y r)) <$> z
    

    In your example, x = (+), y = (+1) and z = a, so we get...

    (\r -> r + (r + 1)) <$> a
    

    ... which adds each value in a to itself plus one:

    GHCi> (+) <*> (+1) <$> [0..3]
    [1,3,5,7]
    GHCi> ((+) <*> (+1) <$> (*5)) 2
    21