std::cout << "Hello, world" << std::endl; — монада. Плохо что до Страуструпа не доперло, что при перегрузке операторов можно/нужно указывать ассоциативность и приоритет, и что можно вообще было выпендриться и запилить миксфиксную форму как в Агде (тогда можно было бы перегужать операторы if и for).
foo.bar().baz() — тоже монада. Такие конструкции лепят где попало. Увы, ни в одном языке где их лепят нельзя перегужать оператор . и писать полноценные монады.
Для комфортного использования монад в языке должна быть поддержка комбинаторного стиля программирования, и do-нотации. Иначе, ничего серьёзнее однострочников в монадическом стиле не написать.
А зачем они вне хаскеля? Хаскель - среда, где абстакции в виде монад удобны. Но за его пределами где это удобно использовать? Разве что в лисп макросами вкрутить monad-do синтаксис.
Да, на F#. Там есть computation expressions, что делает использование монад на F# таким же простым и удобным как и на Haskell. Более того, совсем необязательно понимать, как устроена монада, чтобы ее успешно использовать.
потому что это и есть костыль. Костыль этот идет оттого, что в других ЯП есть явные контексты. Следствием этого является то, что простейшее foo.bar.baz в хаскеле пишется через глубочайшую жопу. Причем те кто пишет эти монды, даже не понимают что это такое, что особенно забавно. Это бурито, это карлик со страпоном, это контейнер, это волшебство, это кококо, lol. Зато каждый имеет собственное_мнение по этому поводу.
Агде (тогда можно было бы перегужать операторы if и for).
А Вы в курсе, что во многих языках if и for являются не тем говном, которым они являются в агде, а функциями, и полноценными ООП-объектами(как и любая другая функция — частный случай объекта) и с ними вообще можно делать все что угодно? Перегружать, переименовывать, модифицировать, удалять...
Увы, ни в одном языке где их лепят нельзя перегужать оператор .
Чаще всего, видимо, препроцессор разворачивает foo.bar(arg) во что-то типа call(foo, bar, arg). И что Вам даст перегрузка? Допустим это возможно, только зачем? Покажите пример, где это могло бы быть полезно.
Возможность *не* выполнять call, если значение foo мне «не нравится». В контексте foo.bar() это немножко бессмысленно, но в контексте foo.bar().baz().quux() очень даже востребовано.
Возможность *не* выполнять call, если значение foo мне «не нравится»
Это же ад с точки зрения проектирования. Ты смотришь на код и не знаешь что он делает. Максимум на еще можно пойти это явный оператор "?.". То есть вызывающая сторона контролирует отброс плохого значения.
Это же ад с точки зрения проектирования. Ты смотришь на код и не знаешь что он делает.
Так для хаскелистов это считается нормой. У них 90% кода настолько абстрактны, что могут делать абсолютно все что угодно. По-этому какой-либо ризонинг вообще нереален, про функцию даже обычно нельзя сказать корректна она или нет - потому что ее корректность полностью зависит от call-site.
то есть это банальный чейнинг? foo.bar.baz? Это монадический стиль? То есть, ООП — это сплошь и рядом монады? А в хаскеле это костыль имитирующий поведение объектов? Так ведь раньше говорили, что монады — это буритто и анчеладос, и простому быдлу не понять. Зачем же вы разочаровываете адептов?&toBuffer=to buffer
Для монад еще return нужен, через fmap/join он не выражается. И вот его-то на генериках не сделать, потому в вышеприведенной реализации сделано на параметрах.
В новом стандарте будет перегрузка точки. А swift умеет задавать ассоциативность и приоритет при перегрузке или объявлении своих операторов. К тому же там есть проперти. Можно на раз два три монады делать.