Комментарии 4
Здорово, что описана мотивация. Еще wiki.haskell.org/Ru/IO_Inside
Если включить прагму GeneralizedNewtypeDeriving уже не получится использовать прагму Safe - компилятор начинает ругаться. По видимому при deriving с включенным GeneralizedNewtypeDeriving используется unsafeCoerce. А тогда всё это не имеет смыла.
Ну в принципе можно, если придти к соглашению - Ок, мы будем пользоваться GeneralizedNewtypeDeriving, но все даём честное слово не пользоваться unsafeCoerce и подобным ей функциям.
Что касается того, что тяжело блоки композировать. Конечно, писать каждый блок в своей песочнице тяжелее, чем если всё писать в IO. Что делать если оказалось, что блоку необходима ещё одна операция ввода-вывода? Добавить её в RIO. А композировать блоки всё равно придётся в полноценной IO монаде.
И наверное действительно нет смысла писать разные монады для разных блоков. Скорее просто можно ограничить в правах всё приложение - есть доступ к определенным разделам БД, к собственной папке на диске, к часам, к сетевым интерфейсам ну а если по ходу разработки потребуются какие то ещё операции, добавим и их. Но тем не менее будет всё запрещено, что не разрешено.
но все даём честное слово не пользоваться unsafeCoerce и подобным ей функциям.
Поправьте, если не прав, но всякие функции вроде unsafeCoerce
являются встроенными хаками системы типов, когда она не может иначе выразить то, что хочется. Значит, нужно отбивать руки всем, кто использует её бездумно, а каждое употребление следует снабжать подробным комментарием, зачем эта функция используется. Запрещать отдельно использовать её для RIO
тогда избыточно — достаточно общего правила.
Конечно, писать каждый блок в своей песочнице тяжелее, чем если всё писать в IO.
Не об этом идёт речь. С этим-то вообще никто не спорит.
Проблема в следующем: вот некий модуль (собственный ли, из своей библиотеки, из 3rd-party библиотеки) реализует свои функции через RIO
с неким типом Permission
; а зависящий от него модуль хочет ещё некоторые операции или дополнительные сорта прав. Что делать? Расширяете RIO
для этого модуля, а с модулем-зависимостью как быть? Писать адаптер между первоначальным RIO
и новым. Или абстрагировать.
По мнению комментатора выше, абстрагирование должно привести к системе эффектов (кажется, разумный вывод).
И наверное действительно нет смысла писать разные монады для разных блоков. Скорее просто можно ограничить в правах всё приложение
Прощай, модульная разработка.
Restricted IO в Haskell