Когда можно использовать IORef? - PullRequest
59 голосов
/ 19 декабря 2009

Одна вещь, которая всегда смущала меня, это то, что сейчас самое время использовать IORef. Существуют ли какие-либо рекомендации, которые следует соблюдать при принятии решения, использовать ли IORef для задачи? Когда подходящее время использовать Государственную монаду над IORef?

Ответы [ 4 ]

73 голосов
/ 19 декабря 2009

State и его относительный ST оба производят "монолитные" вычисления с состоянием, которые могут выполняться как единицы. Они в основном рассматривают изменчивое состояние как промежуточные данные, которые необходимы для получения результата, но сами по себе не должны представлять интерес для остальной части программы.

С другой стороны, то, что помещается в IORef, - это не «вычисление», которое нужно запустить - это просто блок, содержащий простое значение, которое может быть использовано внутри IO довольно произвольным образом. Это поле может быть помещено в структуры данных, обведено (часть ввода-вывода) программы, заменено ее содержимое, когда это удобно, закрыто функцией и т. Д. На самом деле, довольно много беспорядочной природы переменных и указатели таких языков, как C, могут быть смоделированы с помощью IORefs, предоставляя большую помощь любому опытному программисту C, желающему поддержать свою репутацию способности писать код C на любом языке ... Это то, что определенно следует использовать с осторожностью. 1003 *

Тем не менее, иногда крайне громоздко, если не совершенно невозможно, изолировать все взаимодействия с фрагментом изменяемого состояния в одном блоке кода - некоторые части состояния просто необходимо обойти , помещать в структуры данных и т.д. В главе , посвященной изменчивому состоянию учебного пособия «Напиши себе схему за 48 часов» (кстати, очень рекомендуется), приводится пример. (См. Ссылку для хорошего обсуждения того, почему на самом деле наиболее целесообразно использовать IORef, а не State или ST, для моделирования сред Scheme в определенной конструкции интерпретатора Scheme.)

Короче говоря, эти среды должны быть вложены произвольным образом, поддерживаться между экземплярами взаимодействия с пользователем ((define x 1), напечатанный на схеме REPL, должен, вероятно, привести к тому, что пользователь позже сможет набрать x и вернуться 1 в качестве значения), поместите внутрь объектов моделирование функций Scheme (поскольку функции Scheme близки по окружениям, в которых они созданы) и т. Д.

Подводя итог, я бы сказал, что если задача кажется вполне подходящей для нее, государство будет стремиться предоставить самое чистое решение. Если требуется несколько отдельных частей состояния, возможно, ST может помочь. Однако, если вычисление с состоянием является громоздким или невозможно заблокировать в своем собственном фрагменте кода, состояние должно сохраняться в изменяемой форме в течение большей части жизни сложной программы и т. Д., Тогда IORefs могут быть просто подходящая вещь.

Опять же, если вам нужно что-то вроде изменяемого состояния, которое может передаваться и взаимодействовать с ним посредством кода ввода-вывода, почему бы не проверить STM и его TVars! Они намного приятнее при наличии параллелизма, настолько, что фактически делают решение некоторых задач, связанных с параллелизмом, действительно простым. Это, правда, не имеет отношения к вопросу, поэтому я не буду настаивать на уточнении. : -)

14 голосов
/ 19 декабря 2009

Хм. Вы бы использовали IORef, когда вам нужно какое-то изменяемое состояние, но в однопоточном окружении. Или если вы хотите, чтобы изменяемое поле находилось внутри более крупной структуры, которая, в свою очередь, содержится в переменной синхронизации.

В общем, используйте MVars. У них более надежная семантика.

3 голосов
/ 28 ноября 2011

Лично я бы сказал, что можно использовать IORef с, когда и только тогда, когда вы уже используете IO. В противном случае всегда State, если вам не нужна превосходная производительность ST. Можно использовать несколько потоков состояний с монадой State с несколькими вспомогательными функциями - вы просто делаете состояние кортежом или записью и определяете функции для установки, получения или обновления каждого поля отдельно.

В частности, использование StateT s IO обычно не имеет особого смысла. Если вы уже в IO, у вас уже есть изменяемое состояние, так что вы также можете использовать его - например, ReaderT (IORef s) IO.

1 голос
/ 19 декабря 2009

Я использую STRef, когда состояние локализовано и не требует взаимодействия с окружающей средой.

...