В предыдущей статье (Заберите свои скобки), мы попытались избавиться от скобочек с помощью нового оператора для передачи аргументов. На основе своего опыта пользования оператором, можно конечно подобрать нужный приоритет, но он все равно будет конфликтовать в случаях, которые мы не предусмотрели. Что же делать? У меня есть идея. Вспомним оператор применения, который обозначается долларом (как поговаривают знающие люди, это единственное место, где Haskell-программисты могут его увидеть): Он выглядит каким-то бесполезным - без него не можем что ли функцию применить к аргументу, оставив между ними обычный пробел? Вы будете абсолютно правы, потому что он нужен нам за его определенный приоритет и ассоциативность (хорошо про ассоциативность написано в этой статье). Оператор правоассоциативный (на что указывает буква r в infixr), поэтому и скобки будут группироваться справа: Чем выше это число, тем сильнее операторы будут связаны со своими аргументами. У этого оператора самый низкий приоритет из всех возможных, поэтому его можно использовать где угодно и не боятся, что он окажется внутри у аргументов другого оператора. А что если мы попробуем изменить его ассоциативность на противоположную? Вуаля, теперь это оператор передачи аргументов! Но мы не можем объявить один и тот же оператор с разными ассоциативностями, поэтому пока возьмем то самое имя, которое мы придумали в прошлой статье  -  #. Хоть это и звучит достаточно тривиально, но теперь у нас есть доказательство того, что применение функции к ее аргументу и передача аргументов функции - это одно и то же, разница лишь в ассоциативности: Есть у этих двух операторов еще одно важное сходство: мы можем применять оператор сколько угодно раз. Для применения это работает, потому что мы по сути каждый раз применяем вновь к одному аргументу - результату предудущего применения справа: А для передачи аргументов это работает благодаря частичному применению функции (ведь функции в Haskell уже находятся в каррированной форме)! Но что если мы хотим применять много раз левоассоциативный оператор #  к выражениям без скобок, в которых уже сть эти операторы? У нас ничего не получится, так как компилятор будет считать функцию за отдельный аргумент:  Но можно создать еще одни оператор, у которого будет меньше приоритет, а значит, он не будет принимать во внимание операторы с крепче связанными аргументами: Но вообще хорошо, когда операторы своими символами тебе дают подсказку об их назначении. Не секрет, что мы очень любим стрелки. Этот случай не станет исключением - будем использовать стрелки, чтобы не забыть: применения - справа, аргументы - слева.  Мало того, что в Haskell многие авторы библиотек любят выдумывать новые операторы (прямо как мы сейчас), которые бывает тяжело запомнить; так еще и приоритеты они выбирают исходя из их собственного опыта, который может отличаться от вашего. Операторы выглядят красиво в готовом коде, но при готовке нужно постоянно думать об их приоритетах. Думать больше не придется! У меня есть немного безумная идея: что если мы сможем определять приоритет оператора, просто посмотрев на сам оператор? Нет, мы не будет включать число (которое нельзя использовать вместе с другими символами). Просто операторы с приоритетом пониже, будут длиннее, а значит, их использование будет уместно лишь в крайней необходимости. Раз так, то мы можем просто насоздать много таких операторов (максимум 9) с разными приоритетами и использовать их вместе. Закодируем приоритет операторов передачи аргументов с тире: Приоритет оператора можно посчитать так: 10 - количество тире в операторе. Благодаря наглядному приоритету, мы можем применять операторы с постепенным повышением приоритета, чтобы использовать их в каких-нибудь сложных выражениях. Было бы неплохо провернуть тоже самое и с применениями: А теперь давайте применим их на практике. Пример программы: пытаемся прочесть число из строки пользовательского ввода, если не получается, возвращаем 0. Но обязательно указываем, каким образом мы получили итоговое число. Это вполне себе работает, но читать код будет намного легче, если мы добавим отступов: Вообще в последнее время все больше отдаю предпочтение композиции справа-налево, а не классической слева-направо. И это вовсе не из-за увлечения семитскими языками, просто так удобнее читать программы сверху-вниз, от общего к деталям. Да и смешение двух противоположных направлений композиции заставляет бегать глаза невпопад, сравните: Первый вариант можно конечно переписать так, чтобы выражения выполнялись в правильно порядке, но для этого придется пожертвовать .  и, как следствие, лаконичностью. Да и аппликативные цепочки можно так же рассматривать как композиции справа-налево, так как это по сути передача недостающих аргументов с эффектом (хоть и порядок вычислений тут тоже выходит немного невпопад): Я попробовал так же закодировать операторы функторов/монад/сопряжений в своей экспериментальной базовой библиотеке (да-да, все только ради того, чтобы избавиться от скобочек) и это выглядит даже читаемо. Инженер