Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is function composition in Haskell right associative?

Mathematically the function composition operation is associative. Hence:

f . (g . h) = (f . g) . h 

Thus the function composition operation may be defined to be either left associative or right associative.

Since normal function application in Haskell (i.e. the juxtaposition of terms, not the $ operation) is left associative in my opinion function composition should also be left associative. After all most people in the world (including myself) are used to reading from left to right.

Nevertheless function composition in Haskell is right associative:

infixr 9 . 

I know that it doesn't really make a difference whether the function composition operation is left associative or right associative. Nevertheless I'm curious to know why is it not left associative. Two reasons come to my mind for this design decision:

  1. The makers of Haskell wanted function composition to be logically as similar as the $ operation.
  2. One of the makers of Haskell was a Japanese who found it more intuitive to make function composition right associative instead of left associative.

Jokes aside, is there any beneficial reason for function composition to be right associative in Haskell? Would it make any difference if function composition in Haskell was left associative?

like image 749
Aadit M Shah Avatar asked Dec 03 '13 04:12

Aadit M Shah


People also ask

Why is function composition associative?

The composition of functions is always associative—a property inherited from the composition of relations. That is, if f, g, and h are composable, then f ∘ (g ∘ h) = (f ∘ g) ∘ h. Since the parentheses do not change the result, they are generally omitted.

What is function composition in Haskell?

Composing functions is a common and useful way to create new functions in Haskell. Haskell composition is based on the idea of function composition in mathematics. In mathematics, if you have two functions f(x) and g(x), you compute their composition as f(g(x)). The expression f(g(x)) first calls g and then calls f.

What does the operator do in Haskell?

Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).


1 Answers

In the presence of non-strict evaluation, right-associativity is useful. Let's look at a very dumb example:

foo :: Int -> Int foo = const 5 . (+3) . (`div` 10) 

Ok, what happens when this function is evaluated at 0 when . is infixr?

foo 0 => (const 5 . ((+3) . (`div` 10))) 0 => (\x -> const 5 (((+3) . (`div` 10)) x)) 0 => const 5 (((+3) . (`div` 10)) 0) => 5 

Now, what if . was infixl?

foo 0 => ((const 5 . (+3)) . (`div` 10)) 0 => (\x -> (const 5 . (+3)) (x `div` 10)) 0 => (const 5 . (+3)) (0 `div` 10) => (\x -> const 5 (x + 3)) (0 `div` 10) => const 5 ((0 `div` 10) + 3) => 5 

(I'm sort of tired. If I made any mistakes in these reduction steps, please let me know, or just fix them up..)

They have the same result, yes. But the number of reduction steps is not the same. When . is left-associative, the composition operation may need to be reduced more times - in particular, if a function earlier in the chain decides to shortcut such that it doesn't need the result of the nested computation. The worst cases are the same, but in the best case, right-associativity can be a win. So go with the choice that is sometimes better, instead of the choice that is sometimes worse.

like image 79
Carl Avatar answered Oct 11 '22 16:10

Carl