haskellpartial-applicationpartialfunction

Why does ($ 3) have signuature (a -> b) -> b?


In Learn you a Haskell, it is given the following example:

map ($ 3) [(4+), (10*), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]  

However, I don't understand why this works.

The signatures of the functions are

Prelude> :info ($)
($) :: (a -> b) -> a -> b
Prelude> :t ($ 3)
($ 3) :: Num a => (a -> b) -> b

However, -> is a left-associative operator, so $ :: (a -> b) -> a -> b is actually ((($ :: (a-b))-> a)-> b), so shouldn't 3 in ($ 3) correspond to (a->b) function that is the first "variable" of the function $? i.e why is ($ 3) a function of signature (a -> b) -> b

Source: http://learnyouahaskell.com/higher-order-functions


Solution

  • However, -> is a left-associative operator.

    No, -> is a right-associative operator. In the Learn You a Haskell documentation, it says:

    First of all, notice the type declaration. Before, we didn't need parentheses because -> is naturally right-associative.

    A more verbose version of the type signatures of ($) and ($ 3) are:

    ($) :: (a -> b) -> (a -> b)
    ($ 3) :: Num a => (a -> b) -> b
    

    we can write the type constructors in a more canonical form as:

    ($) :: (->) ((->) a b) ((->) a b)
    ($ 3) :: Num a => (->) ((->) a b) b
    

    This thus means that $ takes a function with signature a -> b, and thus returns a function with signature a -> b, it thus basically acts as id, except that it constrants the input to a function (and not just any type), and that you can use $ easily whereas (`id` 3) is not that elegant.

    If we thus apply 3 to the f $ 3 operator, we know that f will have signature f :: a -> b, and 3 will have type Num a => a. If we work with operator sectioning with ($ 3), we pass 3 as the "second" parameter (in Haskell every function has exactly one parameter, but here we assign it thus to the parameter that is the result of ($) f, this thus means that the type of ($ 3) is Num a => (a -> b) -> b.