Вопрос

Я часто встречаю этот шаблон в коде Haskell:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...

По сути, у вас есть запись опций или что-то подобное, которое изначально задается в начале программы.Поскольку программист ленив, он не хочет нести options запись по всей программе.Он определяет MVar сохранить это - определяется уродливым использованием unsafePerformIO.Программист гарантирует, что состояние устанавливается только один раз и до выполнения какой-либо операции.Теперь каждая часть программы должна использовать unsafePerformIO опять же, просто чтобы извлечь варианты.

По моему мнению, такой переменной считается прагматически чистый (не бейте меня).Существует ли библиотека, которая абстрагирует эту концепцию и гарантирует, что переменная будет установлена ​​только один раз, т.е.что до этой инициализации не выполняется ни один вызов и не нужно писать unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

Это было полезно?

Решение

Если вы используете MVAR для удержания настроек или что-то подобное, почему бы вам не попробовать читателя Monad?

foo :: ReaderT OptionRecord IO ()
foo = do
    options <- ask
    fireMissiles

main = runReaderT foo (OptionRecord "foo")
.

(и обычный читатель, если вам не требуют IO: P)

Другие советы

Тех, кто хотел торговля необходимые ссылочной прозрачности для немного временное удобство, не заслуживает ни чистота, ни удобства.

Это плохая идея.Код, в котором вы это находите, является плохим кодом.*

Нет никакого способа полностью безопасно обернуть этот шаблон, потому что это небезопасный шаблон.Не делайте этого в своем коде.Не ищите безопасный способ сделать это.Безопасного способа сделать это не существует.Положите unsafePerformIO медленно опуститесь на пол и отойдите от консоли...

* Существуют законные причины, по которым люди используют MVAR'ы верхнего уровня, но эти причины по большей части связаны с привязками к внешнему коду или несколькими другими вещами, где альтернатива очень запутанная.Однако в этих случаях, насколько я знаю, MVAR'ами верхнего уровня являются нет доступ осуществляется сзади unsafePerformIO.

Используйте неявные параметры.Они немного менее тяжелые, чем делать каждую функцию иметь Reader или ReaderT в своем типе.Вам нужно изменить сигнатуры типа ваших функций, но я думаю, что такое изменение может быть сценарировано.(Сделает хорошую функцию для Haskell IDE.)

Есть важная причина не использовать этот шаблон.Насколько я знаю, в

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

Haskell не дает никаких гарантий, что options будет оцениваться только один раз.Поскольку результат option — это чистое значение, его можно запомнить и использовать повторно, но его также можно пересчитывать для каждого вызова (т.inlined) и смысл программы не должен меняться (в отличие от вашего случая).

Если вы все же решите использовать этот шаблон, обязательно добавьте {-# NOINLINE options #-}, в противном случае он может быть встроен, и ваша программа выйдет из строя!(И тем самым мы выходим из-под гарантий, предоставляемых языком и системой типов, и полагаемся исключительно на реализацию конкретного компилятора.)

Эта тема широко обсуждалась, и возможные решения хорошо изложены на Haskell Wiki в Изменяемое состояние верхнего уровня.В настоящее время невозможно безопасно абстрагировать этот шаблон без дополнительной поддержки компилятора.

Я часто нахожу этот шаблон в коде haskell:

Читать другой код.

Поскольку программист ленивый, он не хочет нести записи параметров по всей программе.Он определяет MVAR, чтобы сохранить его - определяется уродливым использованием USAFEPERFORMFORMIO.Программист гарантирует, что состояние устанавливается только один раз и до того, как произошла какая-либо операция.Теперь каждая часть программы должна снова использовать USAFEPERFORFORMEIO, просто чтобы извлечь параметры.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top