[Haskell-cafe] Observer pattern in Haskell?
Andy Gimblett
haskell at gimbo.org.uk
Mon Nov 9 10:28:30 EST 2009
Hi Neil,
On 9 Nov 2009, at 14:50, Neil Brown wrote:
>> 1. Does anyone have any comments, on either version?
> There is no way to remove an observer, which is something I'd expect
> to have available. I realise this would require assigning a key to
> each observer (and thus perhaps storing them in an associative map)
> or some way to filter them, but I think if you can only ever add
> observers, it will get awkward.
Good point. This occurred to me when I referred to the Gang of Four
book, while changing names for consistency. I must confess, in my
current project I haven't needed it, but I see your point.
>> 2. In particular, is the MVar version sensible? I'm aiming for
>> mutual exclusion between threads. I _think_ I've got it, but I'm
>> perhaps not familiar enough with the semantics of MVar to be
>> certain. Advice appreciated. If it _is_ sensible, then is there
>> any reason not to just use this, and discard the IORef version?
> It looks fine (and thread-safe) to me, but I'd agree that you may as
> well just use the MVar version and leave out the IORef version.
Cool, thanks.
>> was a bit surprised at first that the observers were called
>> synchronously. Asynchronous is what I'd expect, and it's also
>> harder to code the asynchronous handlers wrongly. One blocking
>> call (such as putMVar) in a synchronous handler can screw up your
>> whole program by delaying the subsequent observers (and at that
>> stage, the order in which the observers were added begins to matter).
True, but the observers shouldn't be able to access the MVars
directly, I think? They should only be able to use the exposed
interface, which won't let that happen?
> But my idea of how asynchronous would be implemented seems different
> to yours, judging by your description. Why not just augment this
> function in the synchronous version:
>
> notifyObservers :: Subject sub val => sub -> IO ()
> notifyObservers subject =
> do value <- getValue subject
> observers <- getObservers subject
> mapM_ ($ value) observers to become:
>
> notifyObserversAsync :: Subject sub val => sub -> IO ()
> notifyObserversAsync subject =
> do value <- getValue subject
> observers <- getObservers subject
> mapM_ (forkIO . ($ value)) observers
>
> This is what I was expecting to happen -- all the observer actions
> are spawned off into their own thread to run whatever code they want
> (either communicating back to an existing thread, or performing some
> long in-depth action).
Interesting. That might be quite sensible. My thoughts have probably
been coloured by how I've been doing things in wx. Ta for the
suggestion.
Cheers,
-Andy
More information about the Haskell-Cafe
mailing list