Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, _hum_, Вы писали:
__>>мне нравится сама идея — возможность самому расширять любой тип значением undefined, чтобы замкнуть хотя бы какие-то операции
EP>Мне не нравится инфицирование всех выражений undefined'ом.
почему "всех"? можно же дать программисту возможность выбора, в каких операциях может участвовать расширенный тип, а в каких нет (и на этапе компиляции это отслеживать).
__>>>>мм... может, я неправильно выразился. я имел ввиду подход, когда вместо того, чтобы считать a/0 неопределенностью, просто расширяют тип вещественных чисел за счет введения значения NaN, для которого полагается
__>>>> a @ NaN -> NaN
__>>>> NaN @ NaN -> NaN
__>>>>(здесь @ — любая операция)
EP>>>Это аппликативный функтор, а не монада.
__>>а я думал, это что-то из разряда хаскелловской монады Maybe
EP>Каждая монада это аппликативный функтор, но не наоборот. Если использовать именно монадические свойства Maybe, например через Haskell'евский do-синтаксис, то на первом Nothing'е весь поток управления остановится, собственно для этого и происходит заворачивание в do-синтаксис, чтобы был контроль над потоком управления (что особенно видно если вручную расписать замыкания и bind'ы).
EP>Если же речь идёт про лифтование произвольных операций как в твоей табличке выше, то для этого достаточно аппликативного функтора.
не буду спорить, ибо не спец, да и это неприницпиально. речь шла не о конкретных терминах, а о самой идее — погрузить исходный тип в другой тип, чтобы замкнуть операции и тем самым дать возможность автоматического распространения признака нетипичности результата
по обычному пути.
__>>>>в этом случае даже если у вас произойдет деление на нуль, поток управления все равно продолжит течь, как ни в чем не бывало, предоставляя вам свободу выбора, где делать проверку на валидность соответствующего значения.
EP>>>Монада в этом контексте как раз и отличается от аппликативного функтора тем что может прервать поток управления, так как весь этот поток управления протекает через неё.
__>>ну, я не спец. но интуиция мне подсказывает, что монады в чистом функциональном языке программирования вводились не для того, чтобы туда протаскивать такие императивные вещи, как исключения. возможно, я ошибаюсь.
EP>Их изначально именно и протаскивали ради императивных вещей, в частности таких как ввод-вывод.
да, но не так, чтобы повторить императивные вещи, а чтобы смоделировать императивность через функциональность (по крайней мере мне так казалось).
EP>Собственно исключения в Haskell именно как монада и реализованы.
ну так да, монада, которая тоже, наскоько я понял, "распространяет исключение" по обычному пути, а не меняет путь потока выполнения, как в императивном языке.
1.1 Exception monad
[...]
There is an old dispute between C++ programmers on whether exceptions or error return codes are the right way. Also Niklaus Wirth considered exceptions to be the reincarnation of GOTO and thus omitted them in his languages. Haskell solves the problem a diplomatic way: Functions return error codes, but the handling of error codes does not uglify the calling code.
__>>>>в случае же с эксепшенами обычный поток управления с необходимостью будет прерываться. а значит, программисту придется "всовывать" в обычную логику еще и логику перехватов и обработок исключений.
EP>>>Вообще-то наоборот — с исключениями мы имеем обычную логику не замусоренную проверками и обработками. Обработка же обычно происходит где-то наверху стэка.
__>>ну как же не замусоренную, если вам придется продумывать "а что будет, если вот именно в этом месте поток исполнения прервется и пойдет по совсем другому пути" и вставлять предусматривающий такой ход код?
EP>Если речь идёт про Exception safety, то на C++ обычно всё что требуется для basic guarantee было бы и без исключений.
ну так речь о том, какие средства появились для поддержки этого
__>>кроме того, одна и та же нештатная ситуация может быть критической в одном случае и некритической в другом. и если она может возникнуть, например, в функции f() которую вы используете в нескольких местах, то вам придется во всех местах использования ставить трай-кэтчи, замусоривая код,
EP>Почему же во всех местах использования?
Только в тех, где это критично.
ну, если вы где-то не поставите катч, то программа у вас повалится, даже если в том месте исключение не будет для вас критичным.
__>>тогда как в случае с аналогом NaN такой необходимости не будет.
EP>Если в каком-то месте критично чтобы вызов f() прошёл нормально, вернув нормальный результат, то и в случае с NaN'ами придётся городить проверки
да, но в том месте, где это некритично, проверки можно не ставить
__>>другими словами, ексепшены принуждают программиста под угрозой повалить программу ловить их всюду,
EP>Под какой угрозой? Исключения обычно ловятся в очень малом количестве мест, как раз позволяя убрать мусор присутствующий без них на кодах возвратов.
но вам их обязательно надо ловить!

даже там, где вам это некритично.
__>>тогда как "NaN-подход" просто дает возможность узнать валидность вычисления там, где эта валидность действительно принципиальна для программиста.
EP>Почему эта мифическая угроза заставляет ловить везде исключения, но при этом не заставляет проверять NaN-ы?
if(1 == f())
{
do_something();
}
в случае с "NaN" никаких доп. проверок делать не нужно. в случае с эксепшеном обязательно надо ставить трай-катч