Simon Marlow | 8 Jun 10:37 2012
Picon

Proposal: Control.Concurrent.Async

I'd like to add a higher-level concurrency API to the base package. 
This API has grown while I've been working on examples for my book, and 
I'm convinced that we should have something like this in the standard 
libraries.  Here's the API I propose:

http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html

In fact it already exists in at least two packages on Hackage: 'async' 
and 'threads'.  My version is a superset of both of these, except for a 
few small differences (which are up for discussion, of course).

One good reason to have this package is that it avoids some common 
pitfalls, such as forgetting to handle exceptions in your child threads. 
  In the Async API, you get to choose whether to (a) receive the result 
as 'Either SomeException a', or (b) have the exception re-thrown in the 
waiting thread.  You don't get to ignore it altogether.

Another common pitfall avoided by this library is accidentally leaving 
threads running in the background.  This is handled by withAsync:

   withAsync :: IO a -> (Async a -> IO b) -> IO b

the child thread is always cancelled (i.e. killed) when the second 
argument returns or throws an exception, if it hasn't finished already.

I'm opening this up for discussion so that we can tidy up any 
inconsistent details and add any functions that people feel are missing. 
  Naming is obviously up for discussion too.

Cheers,
(Continue reading)

Michael Snoyman | 8 Jun 11:41 2012

Re: Proposal: Control.Concurrent.Async


On Jun 8, 2012 11:37 AM, "Simon Marlow" <marlowsd <at> gmail.com> wrote:
>
> I'd like to add a higher-level concurrency API to the base package. This API has grown while I've been working on examples for my book, and I'm convinced that we should have something like this in the standard libraries.  Here's the API I propose:
>
> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>
> In fact it already exists in at least two packages on Hackage: 'async' and 'threads'.  My version is a superset of both of these, except for a few small differences (which are up for discussion, of course).
>
> One good reason to have this package is that it avoids some common pitfalls, such as forgetting to handle exceptions in your child threads.  In the Async API, you get to choose whether to (a) receive the result as 'Either SomeException a', or (b) have the exception re-thrown in the waiting thread.  You don't get to ignore it altogether.
>
> Another common pitfall avoided by this library is accidentally leaving threads running in the background.  This is handled by withAsync:
>
>  withAsync :: IO a -> (Async a -> IO b) -> IO b
>
> the child thread is always cancelled (i.e. killed) when the second argument returns or throws an exception, if it hasn't finished already.
>
>
> I'm opening this up for discussion so that we can tidy up any inconsistent details and add any functions that people feel are missing.  Naming is obviously up for discussion too.
>
> Cheers,
>        Simon
>
>
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries

What's the advantage to putting this in base instead of a separate package? If it goes in base, it will make it more difficult to upgrade, and take longer for this module to be adopted at all. If possible, I'd opt for a standalone package.

Michael

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Ian Lynagh | 8 Jun 12:04 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Fri, Jun 08, 2012 at 12:41:29PM +0300, Michael Snoyman wrote:
> On Jun 8, 2012 11:37 AM, "Simon Marlow" <marlowsd <at> gmail.com> wrote:
> >
> > I'd like to add a higher-level concurrency API to the base package.
> 
> What's the advantage to putting this in base instead of a separate package?
> If it goes in base, it will make it more difficult to upgrade, and take
> longer for this module to be adopted at all. If possible, I'd opt for a
> standalone package.

I agree. This doesn't sound like it needs to be a package shipped with
GHC, let alone in the base package.

Thanks
Ian
Simon Marlow | 8 Jun 12:07 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 08/06/2012 10:41, Michael Snoyman wrote:

> What's the advantage to putting this in base instead of a separate
> package? If it goes in base, it will make it more difficult to upgrade,
> and take longer for this module to be adopted at all. If possible, I'd
> opt for a standalone package.

Uploading it to Hackage is certainly an option, and there are arguments 
in both directions.  My thinking was:

  - it's a bit small for a package by itself. There's a lot of
    overhead for a package (github repo, Haskell Platform proposal,
    issue tracker, blah blah)

  - To avoid further fragmentation, I would like this package to
    be more visible, especially if we go to the trouble as a community
    of building some consensus around it.

  - The obvious package name 'async' is already taken

Cheers,
	Simon
Michael Snoyman | 8 Jun 12:29 2012

Re: Proposal: Control.Concurrent.Async


On Jun 8, 2012 1:07 PM, "Simon Marlow" <marlowsd <at> gmail.com> wrote:
>
> On 08/06/2012 10:41, Michael Snoyman wrote:
>
>> What's the advantage to putting this in base instead of a separate
>> package? If it goes in base, it will make it more difficult to upgrade,
>> and take longer for this module to be adopted at all. If possible, I'd
>> opt for a standalone package.
>
>
> Uploading it to Hackage is certainly an option, and there are arguments in both directions.  My thinking was:
>
>  - it's a bit small for a package by itself. There's a lot of
>   overhead for a package (github repo, Haskell Platform proposal,
>   issue tracker, blah blah)
>
>  - To avoid further fragmentation, I would like this package to
>   be more visible, especially if we go to the trouble as a community
>   of building some consensus around it.
>
>  - The obvious package name 'async' is already taken
>
>
> Cheers,
>        Simon

Maybe we could address some of those issues: perhaps Peter Simons would be willing to forfeit the package name in favor of this updated one. That would provide more consolidation, and let the community-driven package use the obvious name.

Michael

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Marlow | 8 Jun 15:52 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 08/06/2012 11:29, Michael Snoyman wrote:
>
> On Jun 8, 2012 1:07 PM, "Simon Marlow" <marlowsd <at> gmail.com
> <mailto:marlowsd <at> gmail.com>> wrote:
>  >
>  > On 08/06/2012 10:41, Michael Snoyman wrote:
>  >
>  >> What's the advantage to putting this in base instead of a separate
>  >> package? If it goes in base, it will make it more difficult to upgrade,
>  >> and take longer for this module to be adopted at all. If possible, I'd
>  >> opt for a standalone package.
>  >
>  >
>  > Uploading it to Hackage is certainly an option, and there are
> arguments in both directions.  My thinking was:
>  >
>  >  - it's a bit small for a package by itself. There's a lot of
>  >   overhead for a package (github repo, Haskell Platform proposal,
>  >   issue tracker, blah blah)
>  >
>  >  - To avoid further fragmentation, I would like this package to
>  >   be more visible, especially if we go to the trouble as a community
>  >   of building some consensus around it.
>  >
>  >  - The obvious package name 'async' is already taken
>  >
>  >
>  > Cheers,
>  >        Simon
>
> Maybe we could address some of those issues: perhaps Peter Simons would
> be willing to forfeit the package name in favor of this updated one.
> That would provide more consolidation, and let the community-driven
> package use the obvious name.

Peter let me know that he's happy for me to reuse the 'async' name. 
I've uploaded the code to github so people can play around with it and 
send me patches easily:

https://github.com/simonmar/async

Cheers,
	Simon
Ryan Newton | 8 Jun 17:11 2012
Picon

Re: Proposal: Control.Concurrent.Async

+1
 
What's the advantage to putting this in base instead of a separate
package? If it goes in base, it will make it more difficult to upgrade,
and take longer for this module to be adopted at all. If possible, I'd
opt for a standalone package.

I thought the idea was that we would try to point people towards using these as a best practice as opposed to using forkIO?

I find that a helper function to fork a child thread with error handling is something I'm always pasting into various projects [1], which I take as a sign it should be easily available.  I never really thought about looking for better threads packages on hackage, because I didn't want to add an extra dependency (or deal with something big and complex).  But if it were standard I would have picked it up!

  -Ryan

[1] P.S.  Non-sequitor: The other little helper function I'm ALWAYS pasting into files is a function to print large numbers with interspersed commas.  I'd like to see THAT in the standard ;-), but I realize there are internationalization issues.
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Thomas Schilling | 8 Jun 18:06 2012

Re: Proposal: Control.Concurrent.Async

On 8 June 2012 11:07, Simon Marlow <marlowsd <at> gmail.com> wrote:
> On 08/06/2012 10:41, Michael Snoyman wrote:
>
>> What's the advantage to putting this in base instead of a separate
>> package? If it goes in base, it will make it more difficult to upgrade,
>> and take longer for this module to be adopted at all. If possible, I'd
>> opt for a standalone package.
>
>
> Uploading it to Hackage is certainly an option, and there are arguments in
> both directions.  My thinking was:
>
>  - it's a bit small for a package by itself. There's a lot of
>   overhead for a package (github repo, Haskell Platform proposal,
>   issue tracker, blah blah)
>
>  - To avoid further fragmentation, I would like this package to
>   be more visible, especially if we go to the trouble as a community
>   of building some consensus around it.
>
>  - The obvious package name 'async' is already taken

I am very much against putting things into base unless there is a
*very* good argument to do this.  If it is supposed to be *the*
standard package, then it belongs into the platform, not base.  If the
platform process is too heavy-weight to discourage this path, then we
need to do something about that rather than sneak things in through
the base library.  It already is a pain to work around issues in the
base library (and many other core packages) since it's (a) takes a
long time for an update to be released, and (b) cannot be upgraded
independently from GHC (pulling in all the changes to other libraries
as well).

I'm glad that the name issues is resolved.  If it is a small library a
platform addition proposal shouldn't be too difficult either.  We just
have to beware of too much bike shedding.

(BTW, have we had another platform proposal since the text package?)
Heinrich Apfelmus | 9 Jun 10:29 2012
Picon

Re: Proposal: Control.Concurrent.Async

Thomas Schilling wrote:
> On 8 June 2012 11:07, Simon Marlow <marlowsd <at> gmail.com> wrote:
>>
>> Uploading it to Hackage is certainly an option, and there are arguments in
>> both directions.  My thinking was:
>> [..]
>>  - it's a bit small for a package by itself. There's a lot of
>>   overhead for a package (github repo, Haskell Platform proposal,
>>   issue tracker, blah blah)

Github provides much of the infrastructure by default, like an issue 
tracker.

> I am very much against putting things into base unless there is a
> *very* good argument to do this.  If it is supposed to be *the*
> standard package, then it belongs into the platform, not base.  If the
> platform process is too heavy-weight to discourage this path, then we
> need to do something about that rather than sneak things in through
> the base library.  It already is a pain to work around issues in the
> base library (and many other core packages) since it's (a) takes a
> long time for an update to be released, and (b) cannot be upgraded
> independently from GHC (pulling in all the changes to other libraries
> as well).
> 
> I'm glad that the name issues is resolved.  If it is a small library a
> platform addition proposal shouldn't be too difficult either.  We just
> have to beware of too much bike shedding.
> 
> (BTW, have we had another platform proposal since the text package?)

+1 for a separate package that is included in the Haskell Platform.

If merging a package into the base library is easier than the process of 
including it in the Haskell Platform, then the latter needs to be fixed.

Best regards,
Heinrich Apfelmus

--
http://apfelmus.nfshost.com
Herbert Valerio Riedel | 9 Jun 10:32 2012
Picon

Re: Proposal: Control.Concurrent.Async

Simon Marlow <marlowsd <at> gmail.com> writes:

>  - To avoid further fragmentation, I would like this package to
>    be more visible, especially if we go to the trouble as a community
>    of building some consensus around it.

...would it help to advertise the new `async` package in the appropriate
places in the Haddoc documentation for `base` to make it more visible?
wren ng thornton | 12 Jun 02:18 2012

Re: Proposal: Control.Concurrent.Async

On 6/9/12 4:32 AM, Herbert Valerio Riedel wrote:
> Simon Marlow<marlowsd <at> gmail.com>  writes:
>
>>   - To avoid further fragmentation, I would like this package to
>>     be more visible, especially if we go to the trouble as a community
>>     of building some consensus around it.
>
> ...would it help to advertise the new `async` package in the appropriate
> places in the Haddoc documentation for `base` to make it more visible?

I wonder if it'd be worthwhile to have a "metabase package" which 
includes all the modules which are, used to be, or 'should' be in base. 
What I mean is not to have an actual package (in the ghc/hackage sense), 
but just to have a single unified Haddock site that covers and 
advertises all of:

* base

* the things broken out from base-3.0 (array, bytestring, containers, 
directory, old-locale, old-time, packedstring, pretty, process, 
random)--- modulo things like packedstring which have been deprecated.

* things broken out from base-4.0 (syb,...)

* things which 'should' be part of base (text? vector? async?)

* but not including all of the HP

Perhaps this already exists in an official incarnation somewhere, but if 
so then it's poorly advertised. The url should be listed in the 
description of the base package on Hackage, at the very least.

--

-- 
Live well,
~wren
Thomas Schilling | 8 Jun 18:31 2012

Re: Proposal: Control.Concurrent.Async

I fixed the docs a tiny bit in: https://github.com/simonmar/async/pull/1

Other comments:

  - Module introduction is missing.

  - There are no tests whatsoever.  I would like to have a few stress
tests that throw lots of asynchronous exceptions to make sure that
exception masking etc behaves correctly.

  - Why is there no waitAnyCancel?
  - Same with waitEitherCancel

On 8 June 2012 09:37, Simon Marlow <marlowsd <at> gmail.com> wrote:
> I'd like to add a higher-level concurrency API to the base package. This API
> has grown while I've been working on examples for my book, and I'm convinced
> that we should have something like this in the standard libraries.  Here's
> the API I propose:
>
> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>
> In fact it already exists in at least two packages on Hackage: 'async' and
> 'threads'.  My version is a superset of both of these, except for a few
> small differences (which are up for discussion, of course).
>
> One good reason to have this package is that it avoids some common pitfalls,
> such as forgetting to handle exceptions in your child threads.  In the Async
> API, you get to choose whether to (a) receive the result as 'Either
> SomeException a', or (b) have the exception re-thrown in the waiting thread.
>  You don't get to ignore it altogether.
>
> Another common pitfall avoided by this library is accidentally leaving
> threads running in the background.  This is handled by withAsync:
>
>  withAsync :: IO a -> (Async a -> IO b) -> IO b
>
> the child thread is always cancelled (i.e. killed) when the second argument
> returns or throws an exception, if it hasn't finished already.
>
>
> I'm opening this up for discussion so that we can tidy up any inconsistent
> details and add any functions that people feel are missing.  Naming is
> obviously up for discussion too.
>
> Cheers,
>        Simon
>
>
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries

--

-- 
Push the envelope. Watch it bend.
Simon Marlow | 12 Jun 12:58 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 08/06/2012 17:31, Thomas Schilling wrote:
> I fixed the docs a tiny bit in: https://github.com/simonmar/async/pull/1
>
> Other comments:
>
>    - Module introduction is missing.

Now added.

>    - There are no tests whatsoever.  I would like to have a few stress
> tests that throw lots of asynchronous exceptions to make sure that
> exception masking etc behaves correctly.

Also added, including a couple of stress tests.  (but the test coverage 
isn't great, I'll try to improve it in due course)

>    - Why is there no waitAnyCancel?
>    - Same with waitEitherCancel

Both added.

I think that now addresses all the comments that people had.

There's one more change I'm thinking about: perhaps instead of

   wait      :: Async a -> IO (Either SomeException a)
   waitThrow :: Async a -> IO a

we should reverse the naming scheme, rename waitThrow to wait and wait 
to something else (waitCatch?).  Rationale: waitThrow seems to be the 
version we need most often, and it's simpler to use.

   wait      :: Async a -> IO a
   waitCatch :: Async a -> IO (Either SomeException a)

Thoughts? Better names for waitCatch?

Latest Haddocks:

   http://community.haskell.org/~simonmar/async/

Repo:

   https://github.com/simonmar/async

Cheers,
	Simon

> On 8 June 2012 09:37, Simon Marlow<marlowsd <at> gmail.com>  wrote:
>> I'd like to add a higher-level concurrency API to the base package. This API
>> has grown while I've been working on examples for my book, and I'm convinced
>> that we should have something like this in the standard libraries.  Here's
>> the API I propose:
>>
>> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>>
>> In fact it already exists in at least two packages on Hackage: 'async' and
>> 'threads'.  My version is a superset of both of these, except for a few
>> small differences (which are up for discussion, of course).
>>
>> One good reason to have this package is that it avoids some common pitfalls,
>> such as forgetting to handle exceptions in your child threads.  In the Async
>> API, you get to choose whether to (a) receive the result as 'Either
>> SomeException a', or (b) have the exception re-thrown in the waiting thread.
>>   You don't get to ignore it altogether.
>>
>> Another common pitfall avoided by this library is accidentally leaving
>> threads running in the background.  This is handled by withAsync:
>>
>>   withAsync :: IO a ->  (Async a ->  IO b) ->  IO b
>>
>> the child thread is always cancelled (i.e. killed) when the second argument
>> returns or throws an exception, if it hasn't finished already.
>>
>>
>> I'm opening this up for discussion so that we can tidy up any inconsistent
>> details and add any functions that people feel are missing.  Naming is
>> obviously up for discussion too.
>>
>> Cheers,
>>         Simon
>>
>>
>>
>> _______________________________________________
>> Libraries mailing list
>> Libraries <at> haskell.org
>> http://www.haskell.org/mailman/listinfo/libraries
>
>
>
Gábor Lehel | 12 Jun 13:38 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jun 12, 2012 at 12:58 PM, Simon Marlow <marlowsd <at> gmail.com> wrote:
> I think that now addresses all the comments that people had.
>
> There's one more change I'm thinking about: perhaps instead of
>
>  wait      :: Async a -> IO (Either SomeException a)
>  waitThrow :: Async a -> IO a
>
> we should reverse the naming scheme, rename waitThrow to wait and wait to
> something else (waitCatch?).  Rationale: waitThrow seems to be the version
> we need most often, and it's simpler to use.
>
>  wait      :: Async a -> IO a
>  waitCatch :: Async a -> IO (Either SomeException a)
>
> Thoughts? Better names for waitCatch?
>
> Latest Haddocks:
>
>  http://community.haskell.org/~simonmar/async/

Two small ones:

- In the documentation for cancel: "Has no effect if the Async has
already", it seems like something might have been cut off.

- Can we find a more accurate name for tryWait? It doesn't try and
possibly fail to wait, it avoids waiting altogether. Maybe don'tWait,
although that doesn't say what it does do. The only other idea I have
is 'check' which is not very descriptive...

>
> Repo:
>
>  https://github.com/simonmar/async
>
> Cheers,
>        Simon
>
>
>
>
>> On 8 June 2012 09:37, Simon Marlow<marlowsd <at> gmail.com>  wrote:
>>>
>>> I'd like to add a higher-level concurrency API to the base package. This
>>> API
>>> has grown while I've been working on examples for my book, and I'm
>>> convinced
>>> that we should have something like this in the standard libraries.
>>>  Here's
>>> the API I propose:
>>>
>>>
>>> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>>>
>>> In fact it already exists in at least two packages on Hackage: 'async'
>>> and
>>> 'threads'.  My version is a superset of both of these, except for a few
>>> small differences (which are up for discussion, of course).
>>>
>>> One good reason to have this package is that it avoids some common
>>> pitfalls,
>>> such as forgetting to handle exceptions in your child threads.  In the
>>> Async
>>> API, you get to choose whether to (a) receive the result as 'Either
>>> SomeException a', or (b) have the exception re-thrown in the waiting
>>> thread.
>>>  You don't get to ignore it altogether.
>>>
>>> Another common pitfall avoided by this library is accidentally leaving
>>> threads running in the background.  This is handled by withAsync:
>>>
>>>  withAsync :: IO a ->  (Async a ->  IO b) ->  IO b
>>>
>>> the child thread is always cancelled (i.e. killed) when the second
>>> argument
>>> returns or throws an exception, if it hasn't finished already.
>>>
>>>
>>> I'm opening this up for discussion so that we can tidy up any
>>> inconsistent
>>> details and add any functions that people feel are missing.  Naming is
>>> obviously up for discussion too.
>>>
>>> Cheers,
>>>        Simon
>>>
>>>
>>>
>>> _______________________________________________
>>> Libraries mailing list
>>> Libraries <at> haskell.org
>>> http://www.haskell.org/mailman/listinfo/libraries
>>
>>
>>
>>
>
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries

--

-- 
Work is punishment for failing to procrastinate effectively.
Simon Marlow | 12 Jun 14:26 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 12/06/2012 12:38, Gábor Lehel wrote:
> On Tue, Jun 12, 2012 at 12:58 PM, Simon Marlow<marlowsd <at> gmail.com>  wrote:
>> I think that now addresses all the comments that people had.
>>
>> There's one more change I'm thinking about: perhaps instead of
>>
>>   wait      :: Async a ->  IO (Either SomeException a)
>>   waitThrow :: Async a ->  IO a
>>
>> we should reverse the naming scheme, rename waitThrow to wait and wait to
>> something else (waitCatch?).  Rationale: waitThrow seems to be the version
>> we need most often, and it's simpler to use.
>>
>>   wait      :: Async a ->  IO a
>>   waitCatch :: Async a ->  IO (Either SomeException a)
>>
>> Thoughts? Better names for waitCatch?
>>
>> Latest Haddocks:
>>
>>   http://community.haskell.org/~simonmar/async/
>
> Two small ones:
>
> - In the documentation for cancel: "Has no effect if the Async has
> already", it seems like something might have been cut off.
>
> - Can we find a more accurate name for tryWait? It doesn't try and
> possibly fail to wait, it avoids waiting altogether. Maybe don'tWait,
> although that doesn't say what it does do. The only other idea I have
> is 'check' which is not very descriptive...

Good point.  How about "poll"?

Cheers,
	Simon

>
>>
>> Repo:
>>
>>   https://github.com/simonmar/async
>>
>> Cheers,
>>         Simon
>>
>>
>>
>>
>>> On 8 June 2012 09:37, Simon Marlow<marlowsd <at> gmail.com>    wrote:
>>>>
>>>> I'd like to add a higher-level concurrency API to the base package. This
>>>> API
>>>> has grown while I've been working on examples for my book, and I'm
>>>> convinced
>>>> that we should have something like this in the standard libraries.
>>>>   Here's
>>>> the API I propose:
>>>>
>>>>
>>>> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>>>>
>>>> In fact it already exists in at least two packages on Hackage: 'async'
>>>> and
>>>> 'threads'.  My version is a superset of both of these, except for a few
>>>> small differences (which are up for discussion, of course).
>>>>
>>>> One good reason to have this package is that it avoids some common
>>>> pitfalls,
>>>> such as forgetting to handle exceptions in your child threads.  In the
>>>> Async
>>>> API, you get to choose whether to (a) receive the result as 'Either
>>>> SomeException a', or (b) have the exception re-thrown in the waiting
>>>> thread.
>>>>   You don't get to ignore it altogether.
>>>>
>>>> Another common pitfall avoided by this library is accidentally leaving
>>>> threads running in the background.  This is handled by withAsync:
>>>>
>>>>   withAsync :: IO a ->    (Async a ->    IO b) ->    IO b
>>>>
>>>> the child thread is always cancelled (i.e. killed) when the second
>>>> argument
>>>> returns or throws an exception, if it hasn't finished already.
>>>>
>>>>
>>>> I'm opening this up for discussion so that we can tidy up any
>>>> inconsistent
>>>> details and add any functions that people feel are missing.  Naming is
>>>> obviously up for discussion too.
>>>>
>>>> Cheers,
>>>>         Simon
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Libraries mailing list
>>>> Libraries <at> haskell.org
>>>> http://www.haskell.org/mailman/listinfo/libraries
>>>
>>>
>>>
>>>
>>
>>
>> _______________________________________________
>> Libraries mailing list
>> Libraries <at> haskell.org
>> http://www.haskell.org/mailman/listinfo/libraries
>
>
>
Gábor Lehel | 12 Jun 15:37 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jun 12, 2012 at 2:26 PM, Simon Marlow <marlowsd <at> gmail.com> wrote:
>> - Can we find a more accurate name for tryWait? It doesn't try and
>> possibly fail to wait, it avoids waiting altogether. Maybe don'tWait,
>> although that doesn't say what it does do. The only other idea I have
>> is 'check' which is not very descriptive...
>
>
> Good point.  How about "poll"?

Definitely better.
Gábor Lehel | 12 Jun 16:30 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jun 12, 2012 at 3:37 PM, Gábor Lehel <illissius <at> gmail.com> wrote:
> On Tue, Jun 12, 2012 at 2:26 PM, Simon Marlow <marlowsd <at> gmail.com> wrote:
>>> - Can we find a more accurate name for tryWait? It doesn't try and
>>> possibly fail to wait, it avoids waiting altogether. Maybe don'tWait,
>>> although that doesn't say what it does do. The only other idea I have
>>> is 'check' which is not very descriptive...
>>
>>
>> Good point.  How about "poll"?
>
> Definitely better.

Just ideas:

- waitAny and company could be generalized to any Foldable. Downside:
it makes the type signatures less obvious. Upside: if people will be
taking the completed Async and removing it from the list (and doing
this frequently), they might prefer something more efficient than a
list.

- If we want to follow the analogy, waitAny could be called 'select'.
Ross Paterson | 14 Jun 17:00 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jun 12, 2012 at 11:58:41AM +0100, Simon Marlow wrote:
> There's one more change I'm thinking about: perhaps instead of
> 
>    wait      :: Async a -> IO (Either SomeException a)
>    waitThrow :: Async a -> IO a
> 
> we should reverse the naming scheme, rename waitThrow to wait and wait 
> to something else (waitCatch?).  Rationale: waitThrow seems to be the 
> version we need most often, and it's simpler to use.
> 
>    wait      :: Async a -> IO a
>    waitCatch :: Async a -> IO (Either SomeException a)
> 
> Thoughts? Better names for waitCatch?

Perhaps the recently freed tryWait would be analogous with
Control.Exception.try.
Chris Kuklewicz | 9 Jun 10:50 2012

Re: Proposal: Control.Concurrent.Async

Your superset API is excellent.  I have one important suggestions: non-blocking
killThread.

By default, when your combinators like 'withAsync' and 'concurrently' use
'cancel' or 'killThread' they should use it in a non-blocking way.  The exported
'cancel' & 'cancelWith' should be unchanged and their documention should note
that they are blocking.

Consider 'concurrently'.  Perhaps there need to to be two 'concurrently'
versions?  One is blocking-killThread and guarantees that both are done or dead
when it returns and the other is non-blocking-killThread and returns ASAP.
Neither can be turned into the other by the user.

Rather than API duplication the 'concurrently' operation could get a new
parameter that selects blocking vs non-blocking killThread.

Hmmm.... the root problem is some Async tasks that, probably due to foreign
calls, are uninterpretable.  Maybe the user could label which Async tasks must
be killed blocking or non-blocking.  The default is non-blocking to avoid
infecting other threads with uninterpretable calls.  When the user needs the
extra property of guaranteed kills the user can change the label.  I have no
immediate idea whether a mutable or immutable label would be better.

-- 
Chris

On 2012/06/08 09:37, Simon Marlow wrote:
> I'd like to add a higher-level concurrency API to the base package. This API has
> grown while I've been working on examples for my book, and I'm convinced that we
> should have something like this in the standard libraries.  Here's the API I
> propose:
> 
> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
> 
> In fact it already exists in at least two packages on Hackage: 'async' and
> 'threads'.  My version is a superset of both of these, except for a few small
> differences (which are up for discussion, of course).
> 
> One good reason to have this package is that it avoids some common pitfalls,
> such as forgetting to handle exceptions in your child threads.  In the Async
> API, you get to choose whether to (a) receive the result as 'Either
> SomeException a', or (b) have the exception re-thrown in the waiting thread. 
> You don't get to ignore it altogether.
> 
> Another common pitfall avoided by this library is accidentally leaving threads
> running in the background.  This is handled by withAsync:
> 
>   withAsync :: IO a -> (Async a -> IO b) -> IO b
> 
> the child thread is always cancelled (i.e. killed) when the second argument
> returns or throws an exception, if it hasn't finished already.
> 
> 
> I'm opening this up for discussion so that we can tidy up any inconsistent
> details and add any functions that people feel are missing.  Naming is obviously
> up for discussion too.
> 
> Cheers,
>     Simon
> 
> 
> 
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
Simon Marlow | 12 Jun 12:33 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 09/06/2012 09:50, Chris Kuklewicz wrote:
> Your superset API is excellent.  I have one important suggestions: non-blocking
> killThread.
>
> By default, when your combinators like 'withAsync' and 'concurrently' use
> 'cancel' or 'killThread' they should use it in a non-blocking way.  The exported
> 'cancel'&  'cancelWith' should be unchanged and their documention should note
> that they are blocking.
>
> Consider 'concurrently'.  Perhaps there need to to be two 'concurrently'
> versions?  One is blocking-killThread and guarantees that both are done or dead
> when it returns and the other is non-blocking-killThread and returns ASAP.
> Neither can be turned into the other by the user.
>
> Rather than API duplication the 'concurrently' operation could get a new
> parameter that selects blocking vs non-blocking killThread.
>
> Hmmm.... the root problem is some Async tasks that, probably due to foreign
> calls, are uninterpretable.  Maybe the user could label which Async tasks must
> be killed blocking or non-blocking.  The default is non-blocking to avoid
> infecting other threads with uninterpretable calls.  When the user needs the
> extra property of guaranteed kills the user can change the label.  I have no
> immediate idea whether a mutable or immutable label would be better.

I appreciate that sometimes cancel may block and that you may want a 
non-blocking cancel, but I don't think that should be the default.

Firstly, the user might find it surprising if when withAsync has 
returned, the Async still performs some more operations (that are not 
inside an exception handler).  I think it's an important guarantee that 
this doesn't happen - otherwise, what can you say with any certainty 
about the behaviour of withAsync?

Secondly, asynchronous cancel is easily implemented by the user, as

   asyncCancel = async . cancel

what a lovely definition :-)  We even get to decide later on to wait for 
the cancel to happen, by waiting on the result of asyncCancel, and we 
can cancel the asyncCancel itself.

Thirdly, asynchronous cancel is less efficient than synchronous cancel, 
because it involves forking a new thread.

I will document carefully that we are using the synchronous cancel and 
the implications of that, and I'll add asyncCancel.

Cheers,
	Simon
Chris Kuklewicz | 15 Jun 15:17 2012

Re: Proposal: Control.Concurrent.Async

I think we should distinguish two cases for "cancel".  I emphasized one case and
rambled a bit in my previous message.  I hope this is clearer.

On 2012/06/12 11:33, Simon Marlow wrote:
> I appreciate that sometimes cancel may block and that you may want a
> non-blocking cancel, but I don't think that should be the default.
> 
> Firstly, the user might find it surprising if when withAsync has returned, the
> Async still performs some more operations (that are not inside an exception
> handler).  I think it's an important guarantee that this doesn't happen -
> otherwise, what can you say with any certainty about the behaviour of withAsync?

I totally 100% have always agreed with that -- for withAsync.  That is the
correct semantics to minimize surprise when sequencing the two IO actions.

But... you also include "race" and "concurrently" where the user has explicitly
asked to go crazy with lots of non-deterministic interleaving.  It may be that
some are talking to blocking FFI things and thus it may be nice to have a
version of these that calls asyncCancel internally:

> Secondly, asynchronous cancel is easily implemented by the user, as
> 
>   asyncCancel = async . cancel

If a user wanted race + asyncCancel then she could copy-paste your module's code
with the changes.  This is certainly something the user could do -- and the
documentation can point out when it would be needed.

I hope I have been clearer.  I was not being crazy and says withAsync needed
asyncCancel.

--

-- 
Chris
Iavor Diatchki | 9 Jun 18:50 2012
Picon

Re: Proposal: Control.Concurrent.Async

Hello,

A nice library, I've had to re-implement similar functionality, so this would be useful!

Some questions about the waiting combinators:

1. I was expecting that `waitAny` and friends, would also return the result of the first computation that completed.  Is there a reason not to do so?
2. Is `waitAny` waiting for one of the Asyncs to complete _successfully_ or is throwing an exception considered as completion?  I am guessing the former, with `waitAnyThrow` providing the latter functionality?
3. As far as I understand, `waitAny` does not stop the other asyncs (it'd be nice to add this note to its documentation, explicitly).  If that's the case, perhaps it's type should be:  `waitAny :: [Async a] -> IO (a,[Async a])`, so that we can keep on waiting for more asyncs, if needed?

-Iavor




On Fri, Jun 8, 2012 at 1:37 AM, Simon Marlow <marlowsd <at> gmail.com> wrote:
I'd like to add a higher-level concurrency API to the base package. This API has grown while I've been working on examples for my book, and I'm convinced that we should have something like this in the standard libraries.  Here's the API I propose:

http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html

In fact it already exists in at least two packages on Hackage: 'async' and 'threads'.  My version is a superset of both of these, except for a few small differences (which are up for discussion, of course).

One good reason to have this package is that it avoids some common pitfalls, such as forgetting to handle exceptions in your child threads.  In the Async API, you get to choose whether to (a) receive the result as 'Either SomeException a', or (b) have the exception re-thrown in the waiting thread.  You don't get to ignore it altogether.

Another common pitfall avoided by this library is accidentally leaving threads running in the background.  This is handled by withAsync:

 withAsync :: IO a -> (Async a -> IO b) -> IO b

the child thread is always cancelled (i.e. killed) when the second argument returns or throws an exception, if it hasn't finished already.


I'm opening this up for discussion so that we can tidy up any inconsistent details and add any functions that people feel are missing.  Naming is obviously up for discussion too.

Cheers,
       Simon



_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Marlow | 9 Jun 23:28 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 09/06/12 17:50, Iavor Diatchki wrote:
> Hello,
> A nice library, I've had to re-implement similar functionality, so this
> would be useful!
>
> Some questions about the waiting combinators:
>
> 1. I was expecting that `waitAny` and friends, would also return the
> result of the first computation that completed.  Is there a reason not
> to do so?
> 2. Is `waitAny` waiting for one of the Asyncs to complete _successfully_
> or is throwing an exception considered as completion?  I am guessing the
> former, with `waitAnyThrow` providing the latter functionality?
> 3. As far as I understand, `waitAny` does not stop the other asyncs
> (it'd be nice to add this note to its documentation, explicitly).  If
> that's the case, perhaps it's type should be:  `waitAny :: [Async a] ->
> IO (a,[Async a])`, so that we can keep on waiting for more asyncs, if
> needed?

All good points.  I don't have many use cases for the waitAny* family 
yet so I'd been holding off refining the API until I had a clearer 
picture of what would be useful for clients.  There are lots of 
possibilities here.  But in light of your comments I have changed the 
type of waitAny to this:

  waitAny :: [Async a] -> IO (Async a, Either SomeException a)

so that it now returns both the Async that completed and its result. 
Since Async supports Eq, the caller can remove the completed one from 
the list and call waitAny again if necessary.

Similarly waitAnyThrow now has this type:

  waitAnyThrow :: [Async a] -> IO (Async a, a)

I've also added a non-blocking wait:

  tryWait :: Async a -> IO (Maybe (Either SomeException a))

so that after a waitAny the caller can check all of the Asyncs for 
completion and remove multiple completed Asyncs from the list.

Latest Haddocks here:

http://community.haskell.org/~simonmar/async/

Cheers,
	Simon

> -Iavor
>
>
>
>
> On Fri, Jun 8, 2012 at 1:37 AM, Simon Marlow <marlowsd <at> gmail.com
> <mailto:marlowsd <at> gmail.com>> wrote:
>
>     I'd like to add a higher-level concurrency API to the base package.
>     This API has grown while I've been working on examples for my book,
>     and I'm convinced that we should have something like this in the
>     standard libraries.  Here's the API I propose:
>
>     http://community.haskell.org/~__simonmar/async-stm/Control-__Concurrent-Async.html
>     <http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html>
>
>     In fact it already exists in at least two packages on Hackage:
>     'async' and 'threads'.  My version is a superset of both of these,
>     except for a few small differences (which are up for discussion, of
>     course).
>
>     One good reason to have this package is that it avoids some common
>     pitfalls, such as forgetting to handle exceptions in your child
>     threads.  In the Async API, you get to choose whether to (a) receive
>     the result as 'Either SomeException a', or (b) have the exception
>     re-thrown in the waiting thread.  You don't get to ignore it altogether.
>
>     Another common pitfall avoided by this library is accidentally
>     leaving threads running in the background.  This is handled by
>     withAsync:
>
>       withAsync :: IO a -> (Async a -> IO b) -> IO b
>
>     the child thread is always cancelled (i.e. killed) when the second
>     argument returns or throws an exception, if it hasn't finished already.
>
>
>     I'm opening this up for discussion so that we can tidy up any
>     inconsistent details and add any functions that people feel are
>     missing.  Naming is obviously up for discussion too.
>
>     Cheers,
>             Simon
>
>
>
>     _________________________________________________
>     Libraries mailing list
>     Libraries <at> haskell.org <mailto:Libraries <at> haskell.org>
>     http://www.haskell.org/__mailman/listinfo/libraries
>     <http://www.haskell.org/mailman/listinfo/libraries>
>
>
wren ng thornton | 12 Jun 02:41 2012

Re: Proposal: Control.Concurrent.Async

On 6/9/12 5:28 PM, Simon Marlow wrote:
> All good points. I don't have many use cases for the waitAny* family yet
> so I'd been holding off refining the API until I had a clearer picture
> of what would be useful for clients. There are lots of possibilities
> here.

The way I typically use it is as follows: The main thread spawns off a 
bunch of heterogeneous workers--- the kind that interact with one 
another in an event-loop like manner (not of the fire-and-forget nor the 
web-server kind). But, the workers may fail/terminate for various 
reasons--- including thrown exceptions, but also more benign things like 
expected failure modes (encoded in normal ADTs or passed along via 
TChans/TVars/etc), and temporary failures that just require some 
'manual' help to get unstuck. After firing them off to do the work, the 
main thread's job is to monitor the workers in order to (a) handle any 
of the failure modes it can, (b) ensure clean and safe shutdown in the 
event of irrecoverable errors.

A related but somewhat different style of using waitAny* parallelism is 
for things like grid managers. Again, there are a bunch of heterogeneous 
worker threads. But this time, rather than focusing on errorful 
termination as above, the focus here is on proper termination. In 
particular, once some job A has finished, we can now start jobs B, C, 
and D which depend on the output of A. In the small scale, you can just 
have A finish by firing off the other jobs; but in the large scale that 
doesn't work. You need to (a) be able to specify the job dependencies 
independently of the work that job is doing, (b) be able to handle 
failures and restarts as above, (c) perform load balancing[1], and so on.

[1] For a proper grid manager this is "real" load balancing by deciding 
which machines a particular job should be run on. But even within a 
single OS process, we can know that certain tasks require more or less 
memory or other resources, and so can alter how aggressively to fire off 
jobs in order to keep from overloading the machine. It's this extreme 
heterogeneity of jobs which is a core part of being a "grid manager" 
IMO; when the jobs are relatively homogeneous (even if doing different 
things) then a lot of these complications go away.

--

-- 
Live well,
~wren
Heka Treep | 13 Jun 16:35 2012
Picon

Re: Proposal: Control.Concurrent.Async

2012/6/8, Simon Marlow <marlowsd <at> gmail.com>:
> I'd like to add a higher-level concurrency API to the base package.
> This API has grown while I've been working on examples for my book, and
> I'm convinced that we should have something like this in the standard
> libraries.  Here's the API I propose:
>
> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>
> In fact it already exists in at least two packages on Hackage: 'async'
> and 'threads'.  My version is a superset of both of these, except for a
> few small differences (which are up for discussion, of course).
>
> One good reason to have this package is that it avoids some common
> pitfalls, such as forgetting to handle exceptions in your child threads.
>   In the Async API, you get to choose whether to (a) receive the result
> as 'Either SomeException a', or (b) have the exception re-thrown in the
> waiting thread.  You don't get to ignore it altogether.
>
> Another common pitfall avoided by this library is accidentally leaving
> threads running in the background.  This is handled by withAsync:
>
>    withAsync :: IO a -> (Async a -> IO b) -> IO b
>
> the child thread is always cancelled (i.e. killed) when the second
> argument returns or throws an exception, if it hasn't finished already.
>
>
> I'm opening this up for discussion so that we can tidy up any
> inconsistent details and add any functions that people feel are missing.
>   Naming is obviously up for discussion too.
>
> Cheers,
> 	Simon
>
>
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>

Hello, Simon.

I have noticed that the computation strategy plays a role for the
'async' function. For example:

asyncWaitCatch :: Int -> Int -> IO (Either String Int)
asyncWaitCatch m n = async (return $ m `div` n) >>= waitCatch >>=
return . either (const $ Left "divide by zero") Right

gives

-- > asyncWaitCatch 4 2
-- Right 2
-- > asyncWaitCatch 1 0
-- Right *** Exception: divide by zero

but

asyncWaitCatch :: Int -> Int -> IO (Either String Int)
asyncWaitCatch m n = async (return $! m `div` n) >>= waitCatch >>=
return . either (const $ Left "divide by zero") Right

gives

-- > asyncWaitCatch 4 2
-- Right 2
-- > asyncWaitCatch 1 0
-- Left "divide by zero"

as expected.

Also, in this kind of a higher-level interface, I would like to have
some form of message passing. It can be done with STM channels, for
example (I wrote a wrapper around threads and STM channels some times
ago, here is how it looks -
https://github.com/treep/hactors/blob/master/Control/Concurrent/Actor.hs).
Sjoerd Visscher | 13 Jun 23:58 2012

Re: Proposal: Control.Concurrent.Async

Hi Simon,

This a really nice and clean library!

I was wondering if it would be useful to have an applicative interface for the concurrently function?
Something like this:

  (page1, page2, page3) 
    <-  runConcurrently $ (,,) 
    <$> Concurrently (getURL "url1") 
    <*> Concurrently (getURL "url2") 
    <*> Concurrently (getURL "url3")

More code here: https://gist.github.com/2926572

Thanks,
Sjoerd

On Jun 8, 2012, at 10:37 AM, Simon Marlow wrote:

> I'd like to add a higher-level concurrency API to the base package. This API has grown while I've been
working on examples for my book, and I'm convinced that we should have something like this in the standard
libraries.  Here's the API I propose:
> 
> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
> 
> In fact it already exists in at least two packages on Hackage: 'async' and 'threads'.  My version is a
superset of both of these, except for a few small differences (which are up for discussion, of course).
> 
> One good reason to have this package is that it avoids some common pitfalls, such as forgetting to handle
exceptions in your child threads.  In the Async API, you get to choose whether to (a) receive the result as
'Either SomeException a', or (b) have the exception re-thrown in the waiting thread.  You don't get to
ignore it altogether.
> 
> Another common pitfall avoided by this library is accidentally leaving threads running in the
background.  This is handled by withAsync:
> 
>  withAsync :: IO a -> (Async a -> IO b) -> IO b
> 
> the child thread is always cancelled (i.e. killed) when the second argument returns or throws an
exception, if it hasn't finished already.
> 
> 
> I'm opening this up for discussion so that we can tidy up any inconsistent details and add any functions
that people feel are missing.  Naming is obviously up for discussion too.
> 
> Cheers,
> 	Simon
> 
> 
> 
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
> 

--
Sjoerd Visscher
https://github.com/sjoerdvisscher/blog
Simon Marlow | 14 Jun 13:42 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 13/06/2012 22:58, Sjoerd Visscher wrote:
> Hi Simon,
>
> This a really nice and clean library!
>
> I was wondering if it would be useful to have an applicative interface for the concurrently function?
Something like this:
>
>    (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.

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.

Cheers,
	Simon

> Thanks,
> Sjoerd
>
> On Jun 8, 2012, at 10:37 AM, Simon Marlow wrote:
>
>> I'd like to add a higher-level concurrency API to the base package. This API has grown while I've been
working on examples for my book, and I'm convinced that we should have something like this in the standard
libraries.  Here's the API I propose:
>>
>> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
>>
>> In fact it already exists in at least two packages on Hackage: 'async' and 'threads'.  My version is a
superset of both of these, except for a few small differences (which are up for discussion, of course).
>>
>> One good reason to have this package is that it avoids some common pitfalls, such as forgetting to handle
exceptions in your child threads.  In the Async API, you get to choose whether to (a) receive the result as
'Either SomeException a', or (b) have the exception re-thrown in the waiting thread.  You don't get to
ignore it altogether.
>>
>> Another common pitfall avoided by this library is accidentally leaving threads running in the
background.  This is handled by withAsync:
>>
>>   withAsync :: IO a ->  (Async a ->  IO b) ->  IO b
>>
>> the child thread is always cancelled (i.e. killed) when the second argument returns or throws an
exception, if it hasn't finished already.
>>
>>
>> I'm opening this up for discussion so that we can tidy up any inconsistent details and add any functions
that people feel are missing.  Naming is obviously up for discussion too.
>>
>> Cheers,
>> 	Simon
>>
>>
>>
>> _______________________________________________
>> Libraries mailing list
>> Libraries <at> haskell.org
>> http://www.haskell.org/mailman/listinfo/libraries
>>
>
> --
> Sjoerd Visscher
> https://github.com/sjoerdvisscher/blog
>
>
>
>
>
Sjoerd Visscher | 14 Jun 10:59 2012

Re: Proposal: Control.Concurrent.Async

And perhaps an Alternative instance would also be useful:

instance Alternative Concurrently where
  empty = Concurrently $ forever (threadDelay maxBound)
  Concurrently as <|> Concurrently bs =
    Concurrently $ either id id <$> race as bs

Where "empty" should be the cheapest way to loop forever, I don't know 
if this is the best way to do that. 

Sjoerd

On Wed, 13 Jun 2012 23:58:54 +0200, Sjoerd Visscher 
<sjoerd <at> w3future.com> wrote:
Hi Simon,
>
> This a really nice and clean library!
>
> I was wondering if it would be useful to have an applicative 
> interface for the concurrently function? Something like this:
>
>   (page1, page2, page3)     <-  runConcurrently $ (,,)     <$> 
> Concurrently (getURL "url1")     <*> Concurrently (getURL "url2")     
> <*> Concurrently (getURL "url3")
>
> More code here: https://gist.github.com/2926572
>
> Thanks,
> Sjoerd
>
> On Jun 8, 2012, at 10:37 AM, Simon Marlow wrote:
>
> > I'd like to add a higher-level concurrency API to the base package. 
> This API has grown while I've been working on examples for my book, 
> and I'm convinced that we should have something like this in the 
> standard libraries.  Here's the API I propose:
> > > 
> http://community.haskell.org/~simonmar/async-stm/Control-Concurrent-Async.html
> > > In fact it already exists in at least two packages on Hackage: 
> 'async' and 'threads'.  My version is a superset of both of these, 
> except for a few small differences (which are up for discussion, of 
> course). 
> > > One good reason to have this package is that it avoids some 
> common pitfalls, such as forgetting to handle exceptions in your 
> child threads.  In the Async API, you get to choose whether to (a) 
> receive the result as 'Either SomeException a', or (b) have the 
> exception re-thrown in the waiting thread.  You don't get to ignore 
> it altogether. 
> > > Another common pitfall avoided by this library is accidentally 
> leaving threads running in the background.  This is handled by 
> withAsync:
> > >  withAsync :: IO a -> (Async a -> IO b) -> IO b
> > > the child thread is always cancelled (i.e. killed) when the 
> second argument returns or throws an exception, if it hasn't finished 
> already. 
> > > > I'm opening this up for discussion so that we can tidy up any 
> inconsistent details and add any functions that people feel are 
> missing.  Naming is obviously up for discussion too. 
> > > Cheers,
> >  Simon
> > > > > _______________________________________________
> > Libraries mailing list
> > Libraries <at> haskell.org
> > http://www.haskell.org/mailman/listinfo/libraries
> > --
> Sjoerd Visscher
> https://github.com/sjoerdvisscher/blog
>
>
>
>
>
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>
>

  --
Sjoerd Visscher
http://w3future.com/

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Sjoerd Visscher | 14 Jun 14:12 2012

Re: Proposal: Control.Concurrent.Async

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

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Marlow | 15 Jun 10:07 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 14/06/2012 13:12, Sjoerd Visscher wrote:
> 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

So what bothered me about this is that it makes 4 threads when I would 
expect 3, and also the asymmetry looks strange.  However see below.

> 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)

I had in mind this:

waitList :: [Async a] -> IO [a]
waitList xs = atomically $ do
   foldr orElse retry (map (void.waitSTM) xs)
   mapM waitSTM xs

but, the problem is that this is an O(N)-sized transaction and it will 
be run O(N) times before it commits, giving us O(N^2).

I've just tested it and it scales terribly, the nested version is much 
better.  So that's an interesting discovery!

I still need to ponder the Applicative version, I'm not familiar with 
Control.Newtype.  I would still like the Traversable abstraction I 
mentioned in my last message.

Cheers,
	Simon
Twan van Laarhoven | 15 Jun 22:04 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/12 10:07, Simon Marlow wrote:
> On 14/06/2012 13:12, Sjoerd Visscher wrote:
>> 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
>
> So what bothered me about this is that it makes 4 threads when I would expect 3,
> and also the asymmetry looks strange.  However see below.

For your enjoyment / horror, I present my implementation of Concurrently that 
uses a single MVar, and exactly one thread per concurrent action. The code is at 
https://gist.github.com/2938456 .

It uses an  MVar (IO (Maybe a)), i.e. each worker thread can post a new action 
that can be done to combine the results; and in the end you hopefully get a 
value of type a.

I'm sure that the code could be improved a lot.

Twan
Ross Paterson | 14 Jun 17:10 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Fri, Jun 08, 2012 at 09:37:16AM +0100, Simon Marlow wrote:
> I'm opening this up for discussion so that we can tidy up any 
> inconsistent details and add any functions that people feel are missing. 
>   Naming is obviously up for discussion too.

I'd expect the arguments of cancelWith to be the other way round.
Then you could say

  cancel = cancelWith ThreadKilled

An alternative, equivalent interface for waitEither and friends would be

  waitEither :: Async a -> Async a -> IO (Either SomeException a)
  waitEitherThrow :: Async a -> Async a -> IO a

This might be conceptually simpler, leaving it to the user to decide
whether to mark the results with Left/Right, or something else, or not.
Similarly the Async now returned by waitAny and friends could be left
to the user.  That would leave the two sets of functions more in line.
Simon Marlow | 15 Jun 15:26 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 14/06/2012 16:10, Ross Paterson wrote:
> On Fri, Jun 08, 2012 at 09:37:16AM +0100, Simon Marlow wrote:
>> I'm opening this up for discussion so that we can tidy up any
>> inconsistent details and add any functions that people feel are missing.
>>    Naming is obviously up for discussion too.
>
> I'd expect the arguments of cancelWith to be the other way round.
> Then you could say
>
>    cancel = cancelWith ThreadKilled

Agreed.

> An alternative, equivalent interface for waitEither and friends would be
>
>    waitEither :: Async a ->  Async a ->  IO (Either SomeException a)
>    waitEitherThrow :: Async a ->  Async a ->  IO a
>
> This might be conceptually simpler, leaving it to the user to decide
> whether to mark the results with Left/Right, or something else, or not.
> Similarly the Async now returned by waitAny and friends could be left
> to the user.  That would leave the two sets of functions more in line.

I liked this suggestion at first, but later concluded that it isn't as 
nice.  The problem is that to convert an 'Async a' to an 'Async (Either 
a b)' has to be done when you create the Async in the first place, or 
else you have to write some STM code to lift the result.  If you're 
writing some STM code anyway, then there's little point in using waitEither.

So I think the waitEither and waitAny families complement each other; 
waitEither handles the lifting of the results into Either for you, which 
is sometimes handy.

Cheers,
	Simon
Ross Paterson | 18 Jun 15:56 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Fri, Jun 15, 2012 at 02:26:51PM +0100, Simon Marlow wrote:
> On 14/06/2012 16:10, Ross Paterson wrote:
> > An alternative, equivalent interface for waitEither and friends would be
> >
> >    waitEither :: Async a ->  Async a ->  IO (Either SomeException a)
> >    waitEitherThrow :: Async a ->  Async a ->  IO a
> >
> > This might be conceptually simpler, leaving it to the user to decide
> > whether to mark the results with Left/Right, or something else, or not.
> > Similarly the Async now returned by waitAny and friends could be left
> > to the user.  That would leave the two sets of functions more in line.
> 
> I liked this suggestion at first, but later concluded that it isn't as 
> nice.  The problem is that to convert an 'Async a' to an 'Async (Either 
> a b)' has to be done when you create the Async in the first place, or 
> else you have to write some STM code to lift the result.  If you're 
> writing some STM code anyway, then there's little point in using waitEither.

The list functions have a similar issue: you have to give them the
right type when you create them if you want them together in a list.
Perhaps a convenient interface for the multiplexing part would be

data AsyncF a = forall r. AsyncF (Async r) (r -> a)

instance Functor AsyncF where
  fmap f (AsyncF a k) = AsyncF a (f . k)

waitSTMF :: AsyncF a -> STM (Either SomeException a)
waitSTMF (AsyncF a k) = fmap (fmap k) (waitSTM a)
Simon Marlow | 3 Jul 14:53 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 18/06/2012 14:56, Ross Paterson wrote:
> On Fri, Jun 15, 2012 at 02:26:51PM +0100, Simon Marlow wrote:
>> On 14/06/2012 16:10, Ross Paterson wrote:
>>> An alternative, equivalent interface for waitEither and friends would be
>>>
>>>     waitEither :: Async a ->   Async a ->   IO (Either SomeException a)
>>>     waitEitherThrow :: Async a ->   Async a ->   IO a
>>>
>>> This might be conceptually simpler, leaving it to the user to decide
>>> whether to mark the results with Left/Right, or something else, or not.
>>> Similarly the Async now returned by waitAny and friends could be left
>>> to the user.  That would leave the two sets of functions more in line.
>>
>> I liked this suggestion at first, but later concluded that it isn't as
>> nice.  The problem is that to convert an 'Async a' to an 'Async (Either
>> a b)' has to be done when you create the Async in the first place, or
>> else you have to write some STM code to lift the result.  If you're
>> writing some STM code anyway, then there's little point in using waitEither.
>
> The list functions have a similar issue: you have to give them the
> right type when you create them if you want them together in a list.
> Perhaps a convenient interface for the multiplexing part would be
>
> data AsyncF a = forall r. AsyncF (Async r) (r ->  a)
>
> instance Functor AsyncF where
>    fmap f (AsyncF a k) = AsyncF a (f . k)
>
> waitSTMF :: AsyncF a ->  STM (Either SomeException a)
> waitSTMF (AsyncF a k) = fmap (fmap k) (waitSTM a)

Good idea.  In fact, I've added a Functor instance for Async itself - it 
required a bit of refactoring but didn't add much overhead.

Cheers,
	Simon
Ross Paterson | 3 Jul 15:17 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jul 03, 2012 at 01:53:16PM +0100, Simon Marlow wrote:
> On 18/06/2012 14:56, Ross Paterson wrote:
> > Perhaps a convenient interface for the multiplexing part would be
> >
> > data AsyncF a = forall r. AsyncF (Async r) (r ->  a)
> >
> > instance Functor AsyncF where
> >    fmap f (AsyncF a k) = AsyncF a (f . k)
> >
> > waitSTMF :: AsyncF a ->  STM (Either SomeException a)
> > waitSTMF (AsyncF a k) = fmap (fmap k) (waitSTM a)
> 
> Good idea.  In fact, I've added a Functor instance for Async itself - it 
> required a bit of refactoring but didn't add much overhead.

So now you can simplify the interfaces of waitEither/waitAny et al?

[BTW, could you generate the new docs with --hyperlink-source?]
Ross Paterson | 3 Jul 18:56 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jul 03, 2012 at 02:17:46PM +0100, Ross Paterson wrote:
> On Tue, Jul 03, 2012 at 01:53:16PM +0100, Simon Marlow wrote:
> > Good idea.  In fact, I've added a Functor instance for Async itself - it 
> > required a bit of refactoring but didn't add much overhead.
> 
> So now you can simplify the interfaces of waitEither/waitAny et al?

Ah, that won't work with the Catch versions.
Simon Marlow | 4 Jul 12:44 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 03/07/2012 14:17, Ross Paterson wrote:
> On Tue, Jul 03, 2012 at 01:53:16PM +0100, Simon Marlow wrote:
>> On 18/06/2012 14:56, Ross Paterson wrote:
>>> Perhaps a convenient interface for the multiplexing part would be
>>>
>>> data AsyncF a = forall r. AsyncF (Async r) (r ->  a)
>>>
>>> instance Functor AsyncF where
>>>     fmap f (AsyncF a k) = AsyncF a (f . k)
>>>
>>> waitSTMF :: AsyncF a ->  STM (Either SomeException a)
>>> waitSTMF (AsyncF a k) = fmap (fmap k) (waitSTM a)
>>
>> Good idea.  In fact, I've added a Functor instance for Async itself - it
>> required a bit of refactoring but didn't add much overhead.
>
> So now you can simplify the interfaces of waitEither/waitAny et al?
>
> [BTW, could you generate the new docs with --hyperlink-source?]

Hackage has the docs now:

http://hackage.haskell.org/packages/archive/async/2.0.1.0/doc/html/Control-Concurrent-Async.html

Cheers,
	Simon
Gábor Lehel | 4 Jul 13:13 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Wed, Jul 4, 2012 at 12:44 PM, Simon Marlow <marlowsd <at> gmail.com> wrote:
> Hackage has the docs now:
>
> http://hackage.haskell.org/packages/archive/async/2.0.1.0/doc/html/Control-Concurrent-Async.html
>
> Cheers,
>         Simon

Perhaps it might make sense to reduce the duplication among the
asyncOn/WithUnmask/etc. variants using an ADT?

e.g.

type Unmask a = (forall b. IO b -> IO b) -> IO a

data Fork a = ForkIO (IO a)
            | ForkOS (IO a)
            | ForkOn Int (IO a)
            | ForkIOWithUnmask (Unmask a)
            | ForkOnWithUnmask Int (Unmask a)

async :: IO a -> IO (Async a)
asyncUsingFork :: Fork a -> IO (Async a)
withAsync :: IO a -> (Async a -> IO b) -> IO b
withAsyncUsingFork :: Fork a -> (Async a -> IO b) -> IO b

(Didn't put much thought into names.)

--

-- 
Your ship was caught in a monadic eruption. Game over.
Johan Tibell | 10 Jul 23:14 2012
Picon

Re: Proposal: Control.Concurrent.Async

Hi all,

Since this thread has been quiet for a while, I'd like to make a call
for any outstanding issues for the proposal to add the async package
(in anticipation for a call for consensus if there aren't any.)

Are there any outstanding issues?

Cheers,
Johan
Lauri Alanko | 14 Jun 23:54 2012
Picon
Picon

Re: Proposal: Control.Concurrent.Async

Quoting "Simon Marlow" <marlowsd <at> gmail.com>:
> Naming is obviously up for discussion too.

I feel that "Async" is a bit too generic and doesn't very precisely  
characterize this particular construct. How about "Future", as similar  
things are called in e.g. Alice  
<http://www.ps.uni-saarland.de/alice/manual/futures.html> and Java  
<http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html>?

Lauri
Simon Marlow | 15 Jun 15:31 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 14/06/2012 22:54, Lauri Alanko wrote:
> Quoting "Simon Marlow" <marlowsd <at> gmail.com>:
>> Naming is obviously up for discussion too.
>
> I feel that "Async" is a bit too generic and doesn't very precisely
> characterize this particular construct. How about "Future", as similar
> things are called in e.g. Alice
> <http://www.ps.uni-saarland.de/alice/manual/futures.html> and Java
> <http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html>?

"Future" evokes notions of parallelism for me, rather than concurrency. 
  I think the term is more often used in a parallel setting.

There's a precedent for using 'async' for concurrency: see the new C# 
and F# async extensions:

http://msdn.microsoft.com/en-us/library/hh191443%28v=vs.110%29.aspx

But naming is hard, and if everyone wanted to use "future" instead I 
wouldn't object very strongly.

Cheers,
	Simon
wren ng thornton | 16 Jun 07:26 2012

Re: Proposal: Control.Concurrent.Async

On 6/15/12 9:31 AM, Simon Marlow wrote:
> On 14/06/2012 22:54, Lauri Alanko wrote:
>> Quoting "Simon Marlow" <marlowsd <at> gmail.com>:
>>> Naming is obviously up for discussion too.
>>
>> I feel that "Async" is a bit too generic and doesn't very precisely
>> characterize this particular construct. How about "Future", as similar
>> things are called in e.g. Alice
>> <http://www.ps.uni-saarland.de/alice/manual/futures.html> and Java
>> <http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html>?
>>
>
> "Future" evokes notions of parallelism for me, rather than concurrency.
> I think the term is more often used in a parallel setting.
>
> There's a precedent for using 'async' for concurrency: see the new C#
> and F# async extensions:
>
> http://msdn.microsoft.com/en-us/library/hh191443%28v=vs.110%29.aspx
>
> But naming is hard, and if everyone wanted to use "future" instead I
> wouldn't object very strongly.

I object to "future" as using an overly general term for one very 
particular instantiation of it. At the very least it must be qualified 
as "concurrent future". Though I'm not particularly opposed to "async"; 
and if there's precedent, then all the better.

--

-- 
Live well,
~wren
Conrad Parker | 19 Jun 03:06 2012

Re: Proposal: Control.Concurrent.Async

On 16 June 2012 13:26, wren ng thornton <wren <at> freegeek.org> wrote:
> On 6/15/12 9:31 AM, Simon Marlow wrote:
>>
>> On 14/06/2012 22:54, Lauri Alanko wrote:
>>>
>>> Quoting "Simon Marlow" <marlowsd <at> gmail.com>:
>>>>
>>>> Naming is obviously up for discussion too.
>>>
>>>
>>> I feel that "Async" is a bit too generic and doesn't very precisely
>>> characterize this particular construct. How about "Future", as similar
>>> things are called in e.g. Alice
>>> <http://www.ps.uni-saarland.de/alice/manual/futures.html> and Java
>>>
>>> <http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html>?
>>>
>>
>> "Future" evokes notions of parallelism for me, rather than concurrency.
>> I think the term is more often used in a parallel setting.
>>
>> There's a precedent for using 'async' for concurrency: see the new C#
>> and F# async extensions:
>>
>> http://msdn.microsoft.com/en-us/library/hh191443%28v=vs.110%29.aspx
>>
>> But naming is hard, and if everyone wanted to use "future" instead I
>> wouldn't object very strongly.
>
>
> I object to "future" as using an overly general term for one very particular
> instantiation of it. At the very least it must be qualified as "concurrent
> future". Though I'm not particularly opposed to "async"; and if there's
> precedent, then all the better.

"future" also seems to me to be more about waiting for the result
value, not about doing something concurrently. Then again I work on a
codebase which involves financial futures contracts, which also
involve waiting for a return value ...

Conrad.
wren ng thornton | 16 Jun 07:24 2012

Re: Proposal: Control.Concurrent.Async

On 6/14/12 5:54 PM, Lauri Alanko wrote:
> Quoting "Simon Marlow" <marlowsd <at> gmail.com>:
>> Naming is obviously up for discussion too.
>
> I feel that "Async" is a bit too generic and doesn't very precisely
> characterize this particular construct. How about "Future", as similar
> things are called in e.g. Alice
> <http://www.ps.uni-saarland.de/alice/manual/futures.html> and Java
> <http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html>?

"Future" is a generic term for a particular way of thinking about the 
life cycle of variables (both in AliceML, Mozart/Oz, and in the 
literature). From this perspective *all* variables are futures. For 
example, in the AliceML url you provide, they specifically qualify the 
different kinds of futures:

* concurrent futures --- something like Async

* lazy futures --- what Haskell has by default

* promised futures --- for tying the knot; akin to "static" in Java

* immediate futures (not mentioned on the AliceML page) --- the standard 
all-at-once way of introducing, binding, and evaluating variables.

Of course, the concurrent/lazy/promised qualifiers can be combined since 
they define orthogonal axes of temporal distinction.

--

-- 
Live well,
~wren
wren ng thornton | 16 Jun 09:23 2012

Re: Proposal: Control.Concurrent.Async

On 6/16/12 1:24 AM, wren ng thornton wrote:
> "Future" is a generic term for a particular way of thinking about the
> life cycle of variables (both in AliceML, Mozart/Oz, and in the
> literature). From this perspective *all* variables are futures. For
> example, in the AliceML url you provide, they specifically qualify the
> different kinds of futures:
>
> * concurrent futures --- something like Async
>
> * lazy futures --- what Haskell has by default
>
> * promised futures --- for tying the knot; akin to "static" in Java

Durr, I meant "final" for the non-static members in Java.

> * immediate futures (not mentioned on the AliceML page) --- the standard
> all-at-once way of introducing, binding, and evaluating variables.
>
> Of course, the concurrent/lazy/promised qualifiers can be combined since
> they define orthogonal axes of temporal distinction.

--

-- 
Live well,
~wren
Sjoerd Visscher | 15 Jun 11:39 2012

Re: Proposal: Control.Concurrent.Async

On Fri, 15 Jun 2012 09:07:54  0100, Simon Marlow <marlowsd <at> gmail.com> wrote:
 > I still need to ponder the Applicative version, I'm not familiar with
> Control.Newtype.  I would still like the Traversable abstraction I 
> mentioned in my last message. 

Control.Newtype is not important. I added it just to be able to write

  ala' Concurrently traverse getURL urls

instead of

  runConcurrently $ traverse (Concurrently . getURL) urls

But it is probably nicer to have

  doConcurrently :: Traversable t => (a -> IO b) -> t a -> IO (t b)

then you could write

  doConcurrently getURL urls

and your doConcurrently would just be "doConcurrently id". 

I updated the code at https://gist.github.com/2926572

greetings,
Sjoerd

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Marlow | 3 Jul 15:33 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/2012 10:39, Sjoerd Visscher wrote:
> On Fri, 15 Jun 2012 09:07:54 0100, Simon Marlow <marlowsd <at> gmail.com> wrote:
>  > I still need to ponder the Applicative version, I'm not familiar with
>> Control.Newtype. I would still like the Traversable abstraction I
>> mentioned in my last message.
>
> Control.Newtype is not important. I added it just to be able to write
>
>    ala' Concurrently traverse getURL urls
>
> instead of
>
>    runConcurrently $ traverse (Concurrently . getURL) urls
>
> But it is probably nicer to have
>
>    doConcurrently :: Traversable t => (a -> IO b) -> t a -> IO (t b)
>
> then you could write
>
>    doConcurrently getURL urls
>
> and your doConcurrently would just be "doConcurrently id".
> I updated the code at https://gist.github.com/2926572

Thanks, I've incorporated your Concurrently type, and renamed 
doConcurrently to mapConcurrently (by analogy with mapM).

I released async-2.0.1.0 with the latest round of changes:

http://hackage.haskell.org/package/async

Changes in 2.0.1.0:

     Added a Functor instance for Async

     Added asyncBound, asyncOn, asyncWithUnmask, asyncOnWithUnmask, 
withAsyncBound, withAsyncOn, withAsyncWithUnmask, withAsyncOnWithUnmask.

     Added mapConcurrently

     Added Concurrently (with Applicative and Alternative instances)

Cheers,
	Simon
Sjoerd Visscher | 3 Jul 19:53 2012

Re: Proposal: Control.Concurrent.Async

Cool, thanks!

Did you check the implementation of "empty"? I didn't really think that one through, it was just the first
thing I tried and it seemed to work. I would not be surprised if there's a better way to wait forever.

On Jul 3, 2012, at 3:33 PM, Simon Marlow wrote:

> Thanks, I've incorporated your Concurrently type, and renamed doConcurrently to mapConcurrently (by
analogy with mapM).
> 
> I released async-2.0.1.0 with the latest round of changes:
> 
> http://hackage.haskell.org/package/async
> 
> Changes in 2.0.1.0:
> 
>    Added a Functor instance for Async
> 
>    Added asyncBound, asyncOn, asyncWithUnmask, asyncOnWithUnmask, withAsyncBound, withAsyncOn,
withAsyncWithUnmask, withAsyncOnWithUnmask.
> 
>    Added mapConcurrently
> 
>    Added Concurrently (with Applicative and Alternative instances)
> 
> Cheers,
> 	Simon
> 

--
Sjoerd Visscher
https://github.com/sjoerdvisscher/blog
Twan van Laarhoven | 15 Jun 14:52 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 08/06/12 10:37, Simon Marlow wrote:
> I'd like to add a higher-level concurrency API to the base package.

How does this async package differ from monad-par, from a user's perspective? It 
seems that the latter is intended for pure computations and the implementation 
is more heavy weight. But it can be used for IO as well.

The difference in API is essentially only that async lives in the IO monad, 
whereas monad-par has its own Par monad.

Could and/or should one be implemented in terms of the other?

Twan
Simon Marlow | 15 Jun 15:38 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/2012 13:52, Twan van Laarhoven wrote:
> On 08/06/12 10:37, Simon Marlow wrote:
>> I'd like to add a higher-level concurrency API to the base package.
>
> How does this async package differ from monad-par, from a user's
> perspective? It seems that the latter is intended for pure computations
> and the implementation is more heavy weight. But it can be used for IO
> as well.

monad-par is for pure deterministic parallelism only, since it is based 
around

   runPar :: Par a -> a

So I'm slightly confused by your comment that it can be used for IO as 
well - what do you mean exactly?

I'd say monad-par is much more lightweight than async.  Perhaps not in 
terms of the amount of code in the library, but the overhead of 'fork' 
in monad-par is much less than the overhead of 'async'.

Incidentally, the IVar in monad-par is what I would call a "future" (in 
reference to the other suggestion that we use "Future" instead of "Async").

> The difference in API is essentially only that async lives in the IO
> monad, whereas monad-par has its own Par monad.

Not being in IO is a pretty big difference :)

> Could and/or should one be implemented in terms of the other?

We could implement monad-par in terms of Async, but I doubt it would 
make a lot of difference.  The reverse is obviously not possible.

Cheers,
	Simon
Twan van Laarhoven | 15 Jun 16:42 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/12 15:38, Simon Marlow wrote:
> On 15/06/2012 13:52, Twan van Laarhoven wrote:
>> On 08/06/12 10:37, Simon Marlow wrote:
> monad-par is for pure deterministic parallelism only, since it is based around
>
>    runPar :: Par a -> a
>
> So I'm slightly confused by your comment that it can be used for IO as well -
> what do you mean exactly?

I base this on the documentation of Control.Monad.Par.Unsafe:

     unsafeParIO :: IO a -> p a
     Lift an IO operation into the Par monad.
     These are unsafe (in the normal, Haskell sense) when used with a runPar of 
type `Par a -> a`. If used with a runParIO that stays in the IO monad, then they 
are simply dangerous.

Twan
Simon Marlow | 15 Jun 17:22 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/2012 15:42, Twan van Laarhoven wrote:
> On 15/06/12 15:38, Simon Marlow wrote:
>> On 15/06/2012 13:52, Twan van Laarhoven wrote:
>>> On 08/06/12 10:37, Simon Marlow wrote:
>> monad-par is for pure deterministic parallelism only, since it is
>> based around
>>
>> runPar :: Par a -> a
>>
>> So I'm slightly confused by your comment that it can be used for IO as
>> well -
>> what do you mean exactly?
>
> I base this on the documentation of Control.Monad.Par.Unsafe:
>
> unsafeParIO :: IO a -> p a
> Lift an IO operation into the Par monad.
> These are unsafe (in the normal, Haskell sense) when used with a runPar
> of type `Par a -> a`. If used with a runParIO that stays in the IO
> monad, then they are simply dangerous.

Ah, so runParIO is part of meta-par, not monad-par as such.  There is no 
instance of ParUnsafe for the default monad-par scheduler.

You have a point that with runParIO, meta-par is similar to Async.
However, the goals are quite different: meta-par is aimed at parallel 
throughput rather than concurrency, so you don't necessarily get 
preemption and fairness like you do with forkIO and Async.  If you do 
blocking IO inside unsafeParIO, it is likely that you'll block other 
threads, because meta-par is doing its own scheduling.  So while you 
*can* do IO operations inside the Par monad, the reason is to allow 
nondeterministic parallel computations, rather than true concurrency.

Cheers,
	Simon
Johan Tibell | 15 Jun 17:52 2012
Picon

Re: Proposal: Control.Concurrent.Async

Simon,

Let me know if you want to proceed with this proposal after this
initial batch of comments. If so I'll try to track the open issues
more closely on the proposal's wiki page.

-- Johan
Simon Marlow | 3 Jul 13:08 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/2012 16:52, Johan Tibell wrote:
> Let me know if you want to proceed with this proposal after this
> initial batch of comments. If so I'll try to track the open issues
> more closely on the proposal's wiki page.

I'm definitely keen to have the package in the platform.  The main point 
against is that the package hasn't had a lot of testing in the wild; 
however I think the API is small and obvious enough that this isn't a 
problem.

If you could help with tracking the open issues that would be great!

Cheers,
	Simon
Johan Tibell | 3 Jul 20:27 2012
Picon

Re: Proposal: Control.Concurrent.Async

On Tue, Jul 3, 2012 at 7:08 AM, Simon Marlow <marlowsd <at> gmail.com> wrote:
> I'm definitely keen to have the package in the platform.  The main point
> against is that the package hasn't had a lot of testing in the wild; however
> I think the API is small and obvious enough that this isn't a problem.
>
> If you could help with tracking the open issues that would be great!

I'm a bit swamped this week but I could try to jot down some notes
next week. In the meantime:

If everyone could please consider the package for inclusion into HP
(i.e. try to separate nice to haves from must haves) and list things
that you think must be addressed before inclusion that'd be great.

-- Johan
Sjoerd Visscher | 15 Jun 15:43 2012

Re: Proposal: Control.Concurrent.Async

> > An alternative, equivalent interface for waitEither and friends would be
> >
> >    waitEither :: Async a ->  Async a ->  IO (Either SomeException a)
> >    waitEitherThrow :: Async a ->  Async a ->  IO a
> >
> > This might be conceptually simpler, leaving it to the user to decide
> > whether to mark the results with Left/Right, or something else, or not. 
> > Similarly the Async now returned by waitAny and friends could be left
> > to the user.  That would leave the two sets of functions more in line. 
>
> I liked this suggestion at first, but later concluded that it isn't 
> as nice.  The problem is that to convert an 'Async a' to an 'Async 
> (Either a b)' has to be done when you create the Async in the first 
> place, or else you have to write some STM code to lift the result.  
> If you're writing some STM code anyway, then there's little point in 
> using waitEither. 

What's the problem with converting when you create the Async?

> withAsync (Left  <$> getUrl url1) $ a1 -> do
> withAsync (Right <$> getUrl url2) $ a2 -> do
>   waitEither a1 a2

This seems more explicit to me. And if you really don't care which of 
the results you want, they'll probably have the same type anyway. 

Greetings,
Sjoerd

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Simon Marlow | 15 Jun 15:56 2012
Picon

Re: Proposal: Control.Concurrent.Async

On 15/06/2012 14:43, Sjoerd Visscher wrote:
>> > An alternative, equivalent interface for waitEither and friends
>> would be
>> >
>> > waitEither :: Async a -> Async a -> IO (Either SomeException a)
>> > waitEitherThrow :: Async a -> Async a -> IO a
>> >
>> > This might be conceptually simpler, leaving it to the user to decide
>> > whether to mark the results with Left/Right, or something else, or
>> not. > Similarly the Async now returned by waitAny and friends could
>> be left
>> > to the user. That would leave the two sets of functions more in line.
>> I liked this suggestion at first, but later concluded that it isn't as
>> nice. The problem is that to convert an 'Async a' to an 'Async (Either
>> a b)' has to be done when you create the Async in the first place, or
>> else you have to write some STM code to lift the result. If you're
>> writing some STM code anyway, then there's little point in using
>> waitEither.
>
> What's the problem with converting when you create the Async?
>
>> withAsync (Left <$> getUrl url1) $ a1 -> do
>> withAsync (Right <$> getUrl url2) $ a2 -> do
>>   waitEither a1 a2
>
> This seems more explicit to me. And if you really don't care which of
> the results you want, they'll probably have the same type anyway.

It forces you to decide how the Async is going to be used when it is 
created, which would make it difficult to have an abstract interface 
between the consumer and the producer.  For example, suppose you need to 
use the Async in multiple different places with different waitEithers or 
waitAnys, then it would be inconvenient.

Cheers,
	Simon

Gmane