Usefulness of "function arrows associate to the right"?
Function arrows associate to the right but [...] what is usefulness of this information?
If you see a type signature like, for example, f : String -> Int -> Bool
you need to know the associativity of the function arrow to understand what the type of f
really is:
- if the arrow associates to the left, then the type means
(String -> Int) -> Bool
, that is,f
takes a function as argument and returns a boolean. - if the arrow associates to the right, then the type means
String -> (Int -> Bool)
, that is,f
takes a string as argument and returns a function.
That's a big difference, and if you want to use f
, you need to know which one it is. Since the function arrow associates to the right, you know that it has to be the second option: f
takes a string and returns a function.
Function arrows associate to the right [...] function application associates to the left
These two choices work well together. For example, we can call the f
from above as f "answer" 42
which really means (f "answer") 42
. So we are passing the string "answer"
to f
which returns a function. And then we're passing the number 42
to that function, which returns a boolean. In effect, we're almost using f
as a function with two arguments.
This is the standard way of writing functions with two (or more) arguments in Haskell, so it is a very common use case. Because of the associativity of function application and of the function arrow, we can write this common use case without parentheses.
When defining a two-argument curried function, we usually write something like this:
f :: a -> b -> c
f x y = ...
If the arrow did not associate to the right, the above type would instead have to be spelled out as a -> (b -> c)
. So the usefulness of ->
's associativity is that it saves us from writing too many parentheses when declaring function types.