The usefulness of "function arrow associated to the right"?

Reading http://www.seas.upenn.edu/~cis194/spring13/lectures/04-higher-order.html contains

In particular, note that the arrows of the function are associated on the right, W β†’ X β†’ Y β†’ Z is equivalent to W β†’ (X β†’ (Y β†’ Z)). We can always add or remove parentheses around the rightmost top-level arrow in a type.

Function arrows are connected on the right, but how a function application is associated on the left, what is useful for this information? I feel that I don’t understand something that concerns me, this is a pointless point that function arrows connect to the right. Since the application function is always associated with the left, then is this the only associativity with which I should be associated?

+6
source share
4 answers

Function arrows are linked to the right, but [...] what is useful for this information?

If you see a type signature, for example, f : String -> Int -> Bool , you need to know the associativity of the arrow function in order to understand what type f :

  • if the arrow is associated on the left, then type means (String -> Int) -> Bool , i.e. f takes a function as an argument and returns a boolean.
  • if the arrow is associated to the right, then type means String -> (Int -> Bool) , i.e. f takes a string as an argument and returns a function.

This is a big difference, and if you want to use f , you need to know which one it is. Since the arrow function is associated on the right, you know that it must be the second option: f takes a string and returns a function.

Functional arrows associated with the right [...] function are associated with the left

These two options work well together. For example, we can call f on top as f "answer" 42 , which actually means (f "answer") 42 . So, we pass the string "answer" to f , which returns a function. And then we pass the number 42 this function, which returns a boolean. In fact, we almost use f as a function with two arguments.

This is the standard way to write functions with two (or more) arguments in Haskell, so this is a very common use case. Due to the associativity of the use of functions and arrow functions, we can write this general use case without parentheses.

+14
source

When defining a two-port curry function, we usually write something like this:

 f :: a -> b -> c fxy = ... 

If the arrow is not associated on the right, the above type should instead be written as a -> (b -> c) . Therefore, the usefulness of associativity -> is that it prevents us from writing too many parentheses when declaring function types.

+5
source

If the # operator is "correct associative", this means:

 a # b # c # d = a # (b # (c # d)) 

... for any number of arguments. It behaves like a foldr

It means that:

 a -> b -> c -> d = a -> (b -> (c -> d)) 

Note: a -> (b -> (c -> d)) =/= ((a -> b) -> c) -> d ! It is very important.

This tells us that, say, foldr :

 Ξ»> :t foldr foldr :: (a -> b -> b) -> b -> [a] -> b 

It takes a function of type (a -> b -> b) and then returns ... a function that takes b and then returns ... a function that takes [a] and then returns ... a b . This means that we can use functions such as

 fabc 

because

 fabc = ((fa) b) c 

and f return two functions each time an argument is provided.

In fact, this is not very useful as such, but important information for when we want to interpret and call function types.

However, functions like (++) have associativity. If (++) remained associative, this would be very slow, so it would be correct associative.

+1
source

The early functional Lisp language suffered from overly nested parentheses (which make the code (or even the text (if you don't mind looking at a wider context)) difficult to read. Over time, the developers of the functional language decided to make the functional code easy to read and write for professionals, even at the cost of confusing newcomers with less uniform rules.

In functional code, declaring a type of a function like (String β†’ Int) β†’ Bool is much less common than String β†’ (Int β†’ Bool) functions, because functions that return functions are trademarks of the functional style. Thus, linking the arrows to the right helps reduce the number of brackets (when overloaded, you may need to map the function to a primitive type). For functional applications, this is the opposite.

0
source

Source: https://habr.com/ru/post/987865/


All Articles