[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