A way to avoid a common use of unsafePerformIO

前端 未结 5 834
天命终不由人
天命终不由人 2021-01-03 23:37

I often find this pattern in Haskell code:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomethi         


        
5条回答
  •  庸人自扰
    2021-01-04 00:02

    There is an important reason for not using this pattern. As far as I know, in

    options :: MVar OptionRecord
    options = unsafePerformIO $ newEmptyMVar
    

    Haskell gives no guarantees that options will be evaluated only once. Since the result of option is a pure value, it can be memoized and reused, but it can also be recomputed for every call (i.e. inlined) and the meaning of the program must not change (contrary to your case).

    If you still decide to use this pattern, be sure to add {-# NOINLINE options #-}, otherwise it might get inlined and your program will fail! (And by this we're getting out of the guarantees given by the language and the type system and relying solely on the implementation of a particular compiler.)

    This topic has been widely discussed and possible solutions are nicely summarized on Haskell Wiki in Top level mutable state. Currently it's not possible to safely abstract this pattern without some additional compiler support.

提交回复
热议问题