Есть важная причина не использовать этот шаблон. Насколько я знаю, в
options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar
Haskell не дает никаких гарантий, что options
будет оцениваться только один раз. Поскольку результат option
является чистым значением, его можно запомнить и использовать повторно, но его также можно пересчитать для каждого вызова (т. Е. Встроенного), и значение программы не должно меняться (в отличие от вашего случая).
Если вы все еще решите использовать этот шаблон, обязательно добавьте {-# NOINLINE options #-}
, в противном случае он может оказаться встроенным, и ваша программа завершится ошибкой! (И этим мы отказываемся от гарантий, данных языком и системой типов, и полагаемся исключительно на реализацию конкретного компилятора.)
Эта тема широко обсуждалась, и возможные решения хорошо изложены на Haskell Wiki в Изменяемое состояние верхнего уровня . В настоящее время невозможно безопасно абстрагировать этот шаблон без дополнительной поддержки компилятора.