metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-03-13 11:51 am
Entry tags:

Ссылка с planet haskell, IO monad

Теперь про IO.
В ссылке с прошлого поста товарищ жалуется на то, что IO монада лезет в любую дыру без мыла и заражает в итоге любую более менее осмысленную программу.

В этом плане я не совсем понимаю, почему в хаскеле эта монада - одна на все виды взаимодействия с внешним миром? Например, с моей точки зрения чтение и запись файлов совершенно отличается от обращения к серверу БД, что в свою очередь отличается от разговора с пользователем в консоли, что опять же отличается от взаимодействия в GUI, итд. Еще можно вспомнить работу по сети, работу с COM-портами, FFI итд.

Предположительно, было бы гуманно дать программистам возможность самостоятельно делать IO-подобные монады и расселить разные виды взаимодействия по разным монадам, заодно как-то прикрутить к этим монадам некие атрибуты на тему ленивости и порядка вычислений - т.е. например, запись в лог без разницы в каком порядке будет делаться и вообще должна вычисляться только тогда, когда это значение кому-то интересно.

Это я как-то размышлял на тему, "как бы выглядел хаскель, встроенный в СУБД в качестве языка запросов". Я с трудом могу перейти от размышления над обычной программой в стиле "запустили, ввели данные, получили результат" к постоянно запущенной программе, управляемой событиями типа "сервер, ждет запроса от клиентов" или "GUI приложение ждет нажатия кнопки пользователем".
И от "программа читает файл с состоянием, обрабатывает запрос и сохраняет файл обратно" к "программа живет с внутренним состоянием, которое обрабатывается интегрированным в компилятор/виртуальную машину/интерпретатор движком БД.
Реализация IO мешается в голове, а для СУБД нужна была бы еще одна монада (а может и не одна), отражающая внутреннее состояние, упорядочивающая действия с записями, транзакциями и взаимодействием между различными пользователями, лезущими к одним и тем же данным).

PS: Напомнили в комментариях - эта идея у меня возникла еще потому, что монада IO как бы таскает с собой "состояние внешнего мира". А это самое состояние - оно ни разу не монолитное, и его, если по хорошему, нужно разбить на несколько частей ("пользователь", "файлы", "базы данных", "сторонние системы").

[identity profile] nealar.livejournal.com 2010-03-13 12:32 pm (UTC)(link)
При доступе к БД, вместо State of the World там должон стоять State of Database, если делать по уму.
но практически, к сожалению, неудобно
Ага.
ext_615659: (Default)

[identity profile] akuklev.livejournal.com 2010-03-13 12:33 pm (UTC)(link)
Именно так. Я даже примерно знаю, как надо было сделать, чтобы на практике было удобно. Но сейчас уже поздно (в смысле, для Хаскелла).

[identity profile] nealar.livejournal.com 2010-03-13 01:10 pm (UTC)(link)
Не поздно. Он ещё не настолько популярен, и haskell == GHC - это ещё не родовое проклятие, а только тревожный симптом.

[identity profile] thesz.livejournal.com 2010-03-13 01:16 pm (UTC)(link)
При доступе к БД, вместо State of the World там должон стоять State of Database, если делать по уму.

Который зависит от неизвестной нам части State of the world. Иными словами - просто зависит от state of the world. И получается, что смысла в отдельном State of the Database нет.

[identity profile] metaclass.livejournal.com 2010-03-13 01:22 pm (UTC)(link)
В идеале, СУБД зависит только сама от себя. Взаимодействия с другими клиентами, блокировки, транзакции - это все включено в State of Database.
Во всяком случае, в моих проектах именно так.

[identity profile] thesz.livejournal.com 2010-03-13 01:28 pm (UTC)(link)
У тебя ключевое слово "в идеале". В идеале у тебя получится БД, что хранит ().

Вот смотри: работа БД может переполнить какой-либо ресурс? Например, память или дисковое пространство? Или сокеты. Так, что другим "монадам" не останется, где выполнять свои действия. Если может, то БД неявно взаимодействует с другими монадами, через неизвестный нам канал, спрятанный в State of the world. Если нет, я хочу видеть реализацию этого дела.

Если говорить практически, то сделай монаду для БД по образу и подобию монады транзакционной памяти или рисования в холсте Cairo.

Попробуй с этим поработать. ;)

[identity profile] nealar.livejournal.com 2010-03-13 01:33 pm (UTC)(link)
Чистая функция тоже меняет флаги процессора, показания счётчика реального времени и т.д. Переполнить с помощью чистого вычисления ресурс "память", испортив жизнь других "монад" - запросто. Чем не аналогия?

[identity profile] thesz.livejournal.com 2010-03-13 01:48 pm (UTC)(link)
Ну, да.

Смотри, в GRIN чистые вычисления транслируются в монадический код.

Как ты думаешь, поверх чего работает эта монада? Если там разница между int_plus и launch_missiles?

[identity profile] nealar.livejournal.com 2010-03-13 02:38 pm (UTC)(link)
Я не знаю, что такое GRIN. И уже утерял нить.
Моя мысль была: DBMonad сделать можно и нужно. Но. Монолитное IO тоже имеет право на жизнь, и это можно обосновать.

[identity profile] thesz.livejournal.com 2010-03-13 02:55 pm (UTC)(link)
Я столько раз говорил про GRIN, что мне больно слышать такие слова от столь давнишнего читателя, как ты. ;)

Одна моя мысль такая: часть функциональности базы данных не зависит от IO. Но часть - зависит. Поэтому взаимодействие между FileM и DBM будет, скорее всего, через эту самую IO.

Другая моя мысль такая: DBM и FileM можно сделать вот уже сейчас. И делают, если это действительно нужно (работа с графикой и обработка сигналов в gtk2hs, или транзакционная память, например). Только это привнесёт такую кучу проблем...

[identity profile] nealar.livejournal.com 2010-03-13 03:11 pm (UTC)(link)
Поэтому взаимодействие между FileM и DBM будет, скорее всего, через эту самую IO.
Подсмотрено в hmatrix: работа с внешней библиотекой линейной алгебры идёт через блоки памяти, которые выделает Foreign.Alloc. То есть, IO. Но. Когда функция "посчитать" отработала, отдала всё, что запросила, с точки зрения стороннего наблюдателя - меня, она выглядит вполне чистой: если мы её вызовем повторно, она вернёт то же самое, и ничего не испортит. Вероятно, поэтому, авторы hmatrix завернули её в unsafePerformIO. Лично я, когда переписывал их код для своих целей, так делать не стал. Но, мне кажется, такой подход имеет право на жизнь. Если "что-то пошло не так", то и launch_missiles и int_plus одинаково плюются исключениями.
Конечно, чем сложней задача, тем сильней протекает изоляция, и тем сложней считать, что unsafePerformIO делать честно.
Вторую мысль поддерживаю всеми руками. Сомневаюсь, что для задачи [livejournal.com profile] metaclassа это действительно нужно, но такая библиотека нужна, как proof of concept. Насчёт того, что STM приносит какие-то большие проблемы - слышу первый раз. Интересно.
Касательно GRIN: если бы у меня хватало времени прочитывать все твои ссылки на нерусские статьи, я бы уже был офигеть каким умным. Те же CSP и π-calculus в моё поле зрения попали не помню когда. Всё никак.

[identity profile] thesz.livejournal.com 2010-03-13 03:18 pm (UTC)(link)
>Насчёт того, что STM приносит какие-то большие проблемы - слышу первый раз. Интересно.

Производительность. ;)

Читал обсуждение, что внесение IO действий внутрь STM может её поднять - чтобы не откатываться на верхний уровень транзакции, когда мы можем выполнить некоторые полезные действия с учётом (в голове) того, что ресурс нам недоступен. (примерно, я по памяти)

[identity profile] nealar.livejournal.com 2010-03-13 03:37 pm (UTC)(link)
1. КМК, реализация, когда atomically идёт, пока не натыкается на недоступный ресурс, а потом получает в лоб и откатывается к началу - не единственный способ сделать STM.
2. Первая мысль по поводу "не откатываться на верхний уровень" - надо тоньше на транзакции резать, а не засовывать всю программу в один блок atomically.
3. Вторая мысль - что в STM с рождения есть такой недостаток, и на это нам указываем наличие newTVarIO. Даже у авторов возник случай, когда нам нужно что-то контрабандой протащить за границу монады. А значит, и в реальной жизни где-то такое возникнет.

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 15:49 (UTC) - Expand

(no subject)

[identity profile] nealar.livejournal.com - 2010-03-13 15:56 (UTC) - Expand

[identity profile] nivanych.livejournal.com 2010-03-13 05:30 pm (UTC)(link)
> Производительность. ;)

Не могу найти ссылку, но видел статью,
где прямо указывалось на выигрыш в производительностью,
по сравнению с вариантом с блокировками при большой нагрузке.

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 17:57 (UTC) - Expand

(no subject)

[identity profile] nivanych.livejournal.com - 2010-03-13 18:06 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 19:18 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-19 10:16 (UTC) - Expand

[identity profile] nivanych.livejournal.com 2010-03-13 05:36 pm (UTC)(link)
Вообще-то, общение с базой очень похоже на IO.
Главным образом, потому, что к базе могут обращаться много пользователей.
Я так думаю.

> такую кучу проблем

А каких проблем?
Нет, я конечно, догадываюсь.
Но ты скажи, если тебе не сложно.

[identity profile] thesz.livejournal.com 2010-03-13 05:52 pm (UTC)(link)
Куча проблем.

Ну, самое простое - как совместить БД и рисование? Чтобы мы выбирали из БД и рисовали, рисовали.

Состояние БД у нас одно на всех, и состояние холста тоже. Оба они инкапсулированы в своих монадах.

Здесь либо работа через каналы - в одном потоке БД вычитывает и передаёт результаты в другой поток, - либо ничего другого мне в голову нейдёт. Буду рад услышать другой вариант.

Вот и связь через IO появилась.

(no subject)

[identity profile] nivanych.livejournal.com - 2010-03-13 18:15 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 19:29 (UTC) - Expand

(no subject)

[identity profile] metaclass.livejournal.com - 2010-03-13 18:56 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 19:27 (UTC) - Expand

(no subject)

[identity profile] nealar.livejournal.com - 2010-03-13 20:42 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 20:46 (UTC) - Expand

(no subject)

[identity profile] nealar.livejournal.com - 2010-03-13 22:05 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-13 23:00 (UTC) - Expand

(no subject)

[identity profile] nealar.livejournal.com - 2010-03-13 23:25 (UTC) - Expand

(no subject)

[identity profile] thesz.livejournal.com - 2010-03-14 00:09 (UTC) - Expand

[identity profile] voidex.livejournal.com 2010-03-13 07:34 pm (UTC)(link)
> Переполнить с помощью чистого вычисления ресурс "память", испортив жизнь других "монад" - запросто
Как?

не понял вопроса

[identity profile] nealar.livejournal.com 2010-03-13 08:41 pm (UTC)(link)
В stack overflow загнать чистым выражением как?

Re: не понял вопроса

[identity profile] voidex.livejournal.com 2010-03-14 08:45 pm (UTC)(link)
Ну, чистое выражение надо где-то начать вычислять.
Если мы вычисляем его в IO, и в IO же какие-то проблемы с памятью - беда беда. А если начали вычислять в BD, а в IO беда с памятью, а упало всё равно в BD, то что-то не так в датском королевстве.

[identity profile] blacklion.livejournal.com 2010-03-13 09:04 pm (UTC)(link)
Тупо породить список больше памяти. Вчера дали гиг — влезло. Сегодня дали полгига — не влезло. Программа чисто функциональная. Вчера работала сегодня — нет. Упс.

[identity profile] voidex.livejournal.com 2010-03-14 08:49 pm (UTC)(link)
Чтобы список породить, его надо где-то вычислить. Если в IO дали мало памяти и упало - то всё логично. А если в IO дали мало памяти, а упало в монаде BD, то уже нелогично.
Вот если у нас runBD :: BD a -> IO a, тогда наверное логично.
Но я вообще идею поста не очень понял. Т.е. саму идею понял, но детали очень важны, а их нет.

[identity profile] blacklion.livejournal.com 2010-03-15 07:15 am (UTC)(link)
Нет IO. Нет BD. Есть чистая функциональщина, которая с математико-теоретической точки зрения не зависит от внешнего мира а зависит только от парамтеров и возвращает только результат, никак не влияя на состояние мира. Но на самом-то деле — влияет, так как память у нас не резиновая и такты процессора не из воздуха берутся.

[identity profile] voidex.livejournal.com 2010-03-15 11:53 am (UTC)(link)
Без IO эта чистая функциональщина никакой памяти не отъест, для начала её нужно в это IO завернуть.

(no subject)

[identity profile] blacklion.livejournal.com - 2010-03-15 13:20 (UTC) - Expand

(no subject)

[identity profile] voidex.livejournal.com - 2010-03-15 15:12 (UTC) - Expand

[identity profile] metaclass.livejournal.com 2010-03-13 01:42 pm (UTC)(link)
Умерший диск, переполнение диска или обрывы сети это все подвиды одного состояния "гамон всему, зовите сисадмина". В базах данных в норме низкоуровневые физические подробности изолированы от логической работы с данными, соответственно с физическими тонкостями разбирается только SYSDBA. Т.е. внутри то базы может быть и FileIO но снаружи это никого не волнует никак.
По логике, тогда получается, что нам нужен способ переселиться из FileIO в DBIO где-то внутри СУБД, т.к. внешним клиентам DBIO совершенно не важен.

[identity profile] thesz.livejournal.com 2010-03-13 01:50 pm (UTC)(link)
Это всё ты можешь сделать вот уже прямо сейчас.

И люди так и делают. В третий раз намекну на транзакционную память и на рисование в Cairo. ;)