Почему $! оператор право-ассоциативный?

Я просто изучаю Haskell, и я все еще не совсем понимаю, когда и как принудительная оценка вынуждена

Когда я хочу, чтобы функция оценивала свои аргументы строго, я обнаружил, что пишу

((f $! x) $! y ) $! z

что кажется странным. Не стоит $! быть лево-ассоциативным, чтобы я мог написать

f $! x $! y $! z

и сделать то, что я хочу?

Я полностью недопонимаю $! оператор?

Ответ 1

Аргумент против

Я нашел предложение от 2008 года в haskell-prime сделать операторы $ и $! лево-ассоциативными:

https://ghc.haskell.org/trac/haskell-prime/wiki/ChangeDollarAssociativity

Есть только один аргумент против предложения: "Это сломает много кода".

Аргументы в пользу

Вместо этого даются четыре аргумента в пользу лево-ассоциативного ($), последний из которых совпадает с вашим, и считается самым важным. Короче говоря:

  • 0), учитывая выражение f x y, с двумя приложениями, мы могли бы написать f $ x $ y

  • 1) теперь, с правой ассоциативной ($), мы можем написать f . g . h $ x как f $ g $ h $ x,

    однако: \x -> f $ g $ h $ x ==> f $ g $ h неверно,

    так что писать такие конвейеры с композицией лучше, так как это позволяет упростить очистку кода

  • 2) Левый ассоциативный ($) позволяет устранить больше круглых скобок, в дополнение к тем, которые были исключены с помощью (.), например:

    f (g x) (h y) ==> f $ g x $ h y

  • 3) ваш аргумент: правильная ассоциативная версия $! неудобна из-за того, что она порождает такие вещи, как: ((f $! x) $! y) $! z вместо f $! x $! y $! z

Заключение

Я предлагаю использовать более левую ассоциативную версию операторов приложения, переопределяющую их в начале нашего кода, например:

import Prelude hiding (($), ($!))

infixl 0  $, $!
($), ($!) :: (a -> b) -> a -> b  
f $  x =         f x
f $! x = x `seq` f x

Ответ 2

Это зеркально отображает фиксацию $. Вы можете сделать очень хороший пример для $ и $!, имеющих неправильную фиксацию.