Proposal: Control.Concurrent.Async

Sjoerd Visscher sjoerd at w3future.com
Thu Jun 14 14:12:54 CEST 2012


On Thu, 14 Jun 2012 12:42:51  0100, Simon Marlow <marlowsd at gmail.com> wrote:
On 13/06/2012 22:58, Sjoerd Visscher wrote:
 > >    (page1, page2, page3)
> >      <-  runConcurrently $ (,,)
> >      <$>  Concurrently (getURL "url1")
> >      <*>  Concurrently (getURL "url2")
> >      <*>  Concurrently (getURL "url3")
> >
> > More code here: https://gist.github.com/2926572
>
> I'm not sure about this.  What you get with the above code is a 
> strange nesting of concurrently calls, whereas what the user might 
> expect is for it to behave like the existing concurrently but on 
> 3-tuples instead of pairs. 

Actually, that is what I expected too. So, this is not the way to use 
concurrently?

concurrently3 m1 m2 m3 = (((v1, v2), v3) -> (v1, v2, v3)) <$> 
  concurrently (concurrently m1 m2) m3

Would this be the correct implementation then:

concurrently3 m1 m2 m3 =
  withAsync m1 $ \a1 ->
  withAsync m2 $ \a2 ->
  withAsync m3 $ \a3 ->
  wait3 a1 a2 a3

And can I then write wait3 as

wait3 a1 a2 a3 = (((v1, v2), v3) -> (v1, v2, v3)) <$> do
  withAsync (waitBoth a1 a2) $ \a12 -> waitBoth a12 a3

or does it have to be:

wait3 a1 a2 a3 =
  atomically $ do
    v1 <- waitSTM a1 `orElse` (waitSTM a2 >> waitSTM a3 >> retry)
    v2 <- waitSTM a2 `orElse` (waitSTM a3 >> retry)
    v3 <- waitSTM a3
    return (v1, v2, v3)

If it is this complicated, then (properly written) Applicative and 
Alternative instances are certainly useful. 

> I like the idea of generalising to arbitrary Traversable structures 
> though.  Maybe we could provide something like
>
>    doConcurrently :: Traversable t => t (IO a) -> IO (t a)
>
> I haven't tried to write it, but it looks like it ought to be possible. 

You'll need an Applicative instance for this anyway. 

--
Sjoerd Visscher
https://github.com/sjoerdvisscher/blog




More information about the Libraries mailing list