[Haskell-cafe] Stupid newbie question of the day: why is newMVar in the IO monad?

Erik Hesselink hesselink at gmail.com
Thu Apr 17 15:05:14 UTC 2014


Also note that *if* you create top level mutable variables (which you
shouldn't, generally), you should make sure they're monomorphic.
Especially with newEmptyMVar it's very easy to create a polymorphic
one, which is just 'unsafeCoerce' in disguise:

import Control.Concurrent.MVar
import System.IO.Unsafe

global = unsafePerformIO newEmptyMVar

main = do
  putMVar global 72
  c <- takeMVar global
  putStrLn [c]

On Thu, Apr 17, 2014 at 4:44 PM, Ryan Yates <fryguybob at gmail.com> wrote:
> Also note linked from the global variables page on the wiki is:
> http://www.haskell.org/haskellwiki/Top_level_mutable_state
>
> Important for the `unsafePerformIO` option is the NOINLINE pragma to ensure
> that only one global variable exists.  In the STM case it is also important
> to use `newTVarIO` rather then `unsafePerformIO $ atomically newTVar` which
> does not work.
>
> Ryan
>
>
> On Thu, Apr 17, 2014 at 10:38 AM, Ben Foppa <benjamin.foppa at gmail.com>
> wrote:
>>
>> In my (limited) experience, there are two main solutions to this kind of
>> problem:
>>
>> Dependency-injection, i.e. add the MVar as an explicit parameter to every
>> function you use it in. This is ideal, but it's often a little cumbersome.
>> unsafePerformIO, i.e. just initialize it globally. I've never really had
>> issues with this approach, if used sparingly and appropriately.
>>
>> This might also be relevant:
>> http://www.haskell.org/haskellwiki/Global_variables
>>
>> Hope that helps!
>>
>>
>> On Thu, Apr 17, 2014 at 10:34 AM, Brian Hurt <bhurt at spnz.org> wrote:
>>>
>>> Thanks.  This helps.  I was right to mistrust the unsafePerformIO
>>> "solution".  :-)  What Haskell was telling me is that I need to think about
>>> the scope of the identifiers I'm allocating, and what guarantees I'm making.
>>>
>>>
>>>
>>>
>>>
>>> On Thu, Apr 17, 2014 at 10:26 AM, Danny Gratzer <danny.gratzer at gmail.com>
>>> wrote:
>>>>
>>>> New `MVar` has to return a different memory location every time and this
>>>> is noticeable, it's not referentially transparent.
>>>>
>>>> Consider what would happen if we made the transformation
>>>>
>>>>      let a = newMVar 0
>>>>      let b = newMVar 0
>>>>      putMVar a 1
>>>>      readMVar b
>>>>
>>>> to
>>>>
>>>>     let a = newMVar 0
>>>>          b = a
>>>>      ...
>>>>
>>>> If newMVar was referentially transparent, we can automatically share any
>>>> of it's calls with same arguments since they're supposed to return the same
>>>> thing everytime. Since it's not referentially transparent, back into the IO
>>>> monad it goes.
>>>>
>>>> Also if you do that toplevel counter trick, you want NoInline otherwise
>>>> GHC might just inline it at each occurrence and you'll end up with separate
>>>> counters.
>>>>
>>>> Cheers,
>>>> Danny Gratzer
>>>
>>>
>>>
>>> _______________________________________________
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>
>>
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>


More information about the Haskell-Cafe mailing list