Why is function composition in Haskell right associative?

前端 未结 1 1419
挽巷
挽巷 2021-02-01 02:42

Mathematically the function composition operation is associative. Hence:

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

Thus the function composition operation may

相关标签:
1条回答
  • 2021-02-01 03:31

    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.

    0 讨论(0)
提交回复
热议问题