Подтвердить что ты не робот

Почему композиция функции в правой ассоциации Haskell?

Математически операция компоновки функций ассоциативна. Следовательно:

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

Таким образом, операция композиции функции может быть определена как левая ассоциативная, так и правая ассоциативная.

Так как приложение нормальной функции в Haskell (т.е. сопоставление терминов, а не операция $) остается ассоциативным, то, по моему мнению, композиция функции также должна быть ассоциативной. Ведь большинство людей в мире (включая меня) используются для чтения слева направо.

Тем не менее состав функций в Haskell является правильным ассоциативным:

infixr 9 .

Я знаю, что на самом деле не имеет значения, оставлена ​​ли ассоциация ассоциативной или правой ассоциативной. Тем не менее мне любопытно узнать, почему это не осталось ассоциативным. Мне приходят на ум две причины:

  • Создатели Haskell хотели, чтобы функциональная композиция была логически подобна операции $.
  • Один из создателей Haskell был японцем, который счел более интуитивно понятным, чтобы композиция композиции была правильной ассоциативной, а не левой ассоциативной.

Шутки в сторону, есть ли какая-нибудь полезная причина, чтобы композиция функции была правильной ассоциативной в Haskell? Будет ли иметь значение, если состав функций в Haskell остался ассоциативным?

4b9b3361

Ответ 1

При наличии нестрогой оценки правая ассоциативность полезна. Посмотрите на очень глупый пример:

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

Хорошо, что происходит, когда эта функция оценивается в 0, когда . есть infixr?

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

Теперь, что, если . было 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

(Я как бы устал. Если бы я допустил ошибки в этих шагах сокращения, сообщите мне об этом или просто исправьте их.)

У них одинаковый результат, да. Но количество шагов восстановления не одинаково. Когда . является лево-ассоциативным, операцию компоновки, возможно, нужно уменьшить больше раз, в частности, если функция, ранее существовавшая в цепочке, решает сократить, так что ей не нужен результат вложенных вычислений. Худшие случаи одинаковы, но в лучшем случае право-ассоциативность может быть победой. Так что идите с выбором, который иногда лучше, вместо выбора, который иногда хуже.