<div dir="ltr">Hi Rouan,<div><br></div><div>I recently developed the effective-aspects package [1], which is a library for monadic pointcut/advice aspect-oriented programming (AOP) in Haskell. Essentially we keep track of the aspects (handlers if you think in terms of event-based programming) in a pure state monad.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span style="font-size:12.800000190734863px;font-family:arial,sans-serif">My problem is that the publish method returns IO (), which means that events can only be<br></span><span style="font-size:12.800000190734863px;font-family:arial,sans-serif">published from the IO monad, but I would like events to be 'publish-able' from pure code.</span></blockquote>

<div><br></div><div>In the library, you must define a monad with the AOT transformer on top, say </div><div><br></div><div>type M = AOT IO</div><div>type M' = AOT (StateT String (ErrorT String Identity))</div><div>...</div>
<div><br></div><div>Our model is not tied to the IO monad (rather to an 'AOMonad' class that provides weaving); hence it does supports pure events (join points in AOP terminology). A pseudo-code example is:</div><div>
<br></div><div>-- foo has type A -> m B for some types A, B and monad m</div><div>-- adv has type Advice (A -> m B); which is a type synonym for (A -> m B) -> A -> m B</div><div><br></div><div>do (deploy (aspect (pcCall foo) adv))</div>
<div>      foo # arg</div><div><br></div><div>here the # is the 'open application' operator, which triggers the weaving process that eventually executes the advice.</div><div><br></div><div>The main publication of this work can be found here: <a href="http://hal.archives-ouvertes.fr/docs/00/87/27/82/PDF/TAOSD-EffectiveAspects.pdf">http://hal.archives-ouvertes.fr/docs/00/87/27/82/PDF/TAOSD-EffectiveAspects.pdf</a></div>
<div><br></div><div>I think your particular use case is not described in your email, but if you want to expose some content other than the application's arguments it will need some small work on my part (and a new version of the library). I will be pleased to help you if you are interested in using the library, and if you can wait a little--- I'm really time-constrained this month :)</div>
<div><br>Bests,</div><div><br></div><div>[1] <a href="http://hackage.haskell.org/package/effective-aspects" target="_blank">http://hackage.haskell.org/package/effective-aspects</a></div><div><br></div></div><div class="gmail_extra">
<br><br><div class="gmail_quote">2014-03-28 11:59 GMT+01:00 Rouan van Dalen <span dir="ltr"><<a href="mailto:rvdalen@yahoo.co.uk" target="_blank">rvdalen@yahoo.co.uk</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Cafe,<br>
<br>
I am trying to write a very simple implementation of an event publisher pattern but I am stuck and do<br>
not know how to do this in Haskell.<br>
<br>
I have the following code:<br>
<br>
========================<br>
<br>
<br>
{-# LANGUAGE RankNTypes, NamedFieldPuns #-}<br>
<br>
module Domain.DomainEventPublisher where<br>
<br>
   import Control.Monad (forM_)<br>
<br>
   import HsFu.Data.DateTime<br>
   import Domain.Client<br>
<br>
<br>
   data DomainEvent = ClientChangeAgeDomainEvent<br>
<br>
<br>
   data DomainEventContext =<br>
      DomainEventContext { domainEventContext_event      :: DomainEvent<br>
                         , domainEventContext_occurredOn :: DateTime<br>
                         } deriving (Show)<br>
<br>
<br>
   data DomainEventPublisher = DomainEventPublisher { domainEventPublisher_subscribers :: [DomainEventContext -> IO ()] }<br>
<br>
<br>
   mkEventPublisher :: DomainEventPublisher<br>
   mkEventPublisher = DomainEventPublisher []<br>
<br>
<br>
   subscribe :: DomainEventPublisher -> (DomainEventContext -> IO ()) -> DomainEventPublisher<br>
   subscribe publisher eventHandler =<br>
      DomainEventPublisher { domainEventPublisher_subscribers = eventHandler : (domainEventPublisher_subscribers publisher) }<br>
<br>
<br>
   publish :: DomainEventPublisher -> DomainEventContext -> IO ()<br>
   publish DomainEventPublisher{ domainEventPublisher_subscribers } event =<br>
      forM_ domainEventPublisher_subscribers ($ event)<br>
<br>
========================<br>
<br>
<br>
My problem is that the publish method returns IO (), which means that events can only be<br>
published from the IO monad, but I would like events to be 'publish-able' from pure code.<br>
<br>
I can live with event handlers (passed into the subscribe function) being in the IO monad.<br>
<br>
Is there a better way to implement this pattern in Haskell?<br>
<br>
I have been racking my brain on this for a while now and cannot seem to come up with a<br>
good implementation.<br>
<br>
Regards<br>
--Rouan.<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>Ismael<br>
</div>