[Haskell-cafe] Current situation regarding global IORefs

Brian Hulley brianh at metamilk.com
Fri Apr 21 13:27:30 EDT 2006


Robert Dockins wrote:
> On Apr 21, 2006, at 10:34 AM, Brian Hulley wrote:
>> Robert Dockins wrote:
>>> On Apr 21, 2006, at 9:56 AM, Brian Hulley wrote:
>>>
>>>> Hi -
>>>> I've run into the global mutable state problem described in http://
>>[snip]
>>
>> There is only one GUI for the application and only one control in
>> it can have the keyboard focus so it seems natural to use global
>> state here
>
> I'd suggest you consider not making those assumptions... they are the
> kinds of assumptions that can make later code reuse and maintenance
> more difficult than it should be.  (Obviously, if code reuse/
> maintenance is a low priority then it doesn't matter).
>
>> , but I suppose I could also look into using a state monad. The
>> advantage (perhaps also disadvantage ;-) ) of global state is that
>> it allows me to easily convert all my old C++ singleton classes to
>> Haskell modules...
>
> <ramble type="somewhat coherent">
> Ahhh... the singleton pattern.  There is a debate among OO theorists
> about whether the singleton pattern is actually a good idea.  I tend
> to side with those who say that it is Just Wrong. [snip]

Thanks for the comments. I've now changed everything so that controls use a 
ManagerM monad which wraps up the state instead of using the IO monad so 
there are no longer any global variables. It wasn't as difficult as I had 
thought and as you say it makes everything much more scalable, although at 
the expense of having to use liftIO in various places.

I've defined my state monad by:

data MState = MState {keyboard:: !Maybe Control} -- etc - other state here 
also
type ManagerM a = StateT MState IO a

and everything works ok. However if I try to use a newtype instead of a type 
(to completely hide the representation) eg

newtype ManagerM a = ManagerM (StateT MState IO a) deriving (Monad, MonadIO, 
MonadState)

it won't compile. Does this mean it is not possible to wrap combined monads 
in a newtype? I notice that the examples in tutorials I've looked at tend to 
always just use type instead of newtype.

Another point is that I'm not sure what is the "proper" way to represent the 
state itself ie should each component of the state be a separate IORef to 
avoid having to copy the whole state each time or is it better practice to 
just use an immutable record as I've done above?

Thanks, Brian. 



More information about the Haskell-Cafe mailing list