Is there a way to get the result of "either of three calls to getUrl" as opposed to "all three calls"?
'Cause that's what Mike seems to want.

That's what the Alternative instance of Concurrently is for. The result of `doA <|> doB` is the result of the argument that finished first. (<|>) = race.

firstResult <- runConcurrently (Concurrently (getURL "url1") <|> Concurrently (getURL "url2") <|> Concurrently (getURL "url3"))

or

firstResult <- runConcurrently $ asum $ map (Concurrently . getURL) [ "url1", "url2", "url3" ] 

On Fri, Mar 20, 2020 at 9:44 AM Artem Pelenitsyn <a.pelenitsyn@gmail.com> wrote:
Hey Niklas,

Thanks for your explanation -- it was useful to read.

Is there a way to get the result of "either of three calls to getUrl" as opposed to "all three calls"?
'Cause that's what Mike seems to want.

--
Best regards,
Artem


On Thu, 19 Mar 2020 at 21:38, Niklas Hambüchen <mail@nh2.me> wrote:
Hey Mike,

>     f <- async getPages
>     cancel f

you haven't read the PR I linked carefully enough yet :)

It essentially says to never use the `async` function, as that is almost never what you want

Full docs, with what you need to read highlighted:
https://github.com/nh2/async/blob/1d96dc555b70a4c5aba07f15d0c7895545eb8582/Control/Concurrent/Async.hs#L21-L143

> Am I guaranteed the the getURL() calls will definitely have either finished, or cancel?

For

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

you are guaranteed that when `runConcurrently` returns, all 3 downloads have finished successfully.

Only the `instance Alternative Concurrently` (that is, when you use <|>) is implemented in terms of `race`.

You are using <*>, as implemented in the `instance Applicative Concurrently`, which uses `concurrently`, which waits for both of two actions.

Your code in

> main = do
>     f <- async getPages
>     cancel f

does not make much sense:
Here you're starting a thread that would go off do something, but then you immediately cancel that thread, so it won't achieve anything.

You do not need to wrap things into additional `async`s. You can directly do, for example:

    main :: IO ()
    main = do
      (page1, page2, page3) <- runConcurrently $
        (,,)
          <$> Concurrently (getURL "url1")
          <*> Concurrently (getURL "url2")
          <*> Concurrently (getURL "url3")
      putStrLn "Here are the page contents:"
      putStrLn page1
      putStrLn page2
      putStrLn page3

Hope that helps!

Niklas
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.