On 21/04/06, Brian Hulley <[EMAIL PROTECTED]> wrote: > 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. try deriving (Monad, MonadIO, MonadState MState) -- I find that newtype deriving doesn't like guessing at other class parameters, even with the fundeps there.
> 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? If you were to use IORefs/MVars, it would likely be enough to use ReaderT instead of StateT, since you likely wouldn't be replacing your mutable cells, just their contents. Both routes are okay -- note that Haskell data structure nodes are usually just bunches of pointers to values (or more properly, code which returns values) anyway, so you should only be copying a few pointers when updates are made. (In a similar way to how replacing the head of a list is constant time and space, and not linear.) - Cale _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe