How does parTraverse work with [A/E]ffect?

I’m trying to use ado syntax with Aff, Alt, and Maybe a values. Something conceptually like this

getExpensiveThing ∷ MonadAff m ⇒ m (Maybe String)
getExpensiveThing = ado
  (mval1 ∷ Maybe String) ← fetchLocalStorage
  (mval2 ∷ Maybe String) ← fetchNetwork
  (mval3 ∷ Maybe String) ← generateNewBigThingLocally
  in mval1 <|> mval2 <|> mval3

In this case all effects (in this case kind of expensive) are ran and then the alternatives are alt’d. This isn’t what I want, and what I think I want is parTraverse but I don’t quite understand how it works in this setup.

1 Like

Applicative do on its own won’t parallelize things, it’ll only ensure you’re using your type’s Applicative instance rather than its Monad instance. Because Applicative and Monad have to agree, that means that it’ll still run sequentially. Instead, you have to use a newtype wrapper to get parallel execution. For Aff, that’s ParAff, which you can access via the sequential and parallel methods of the Parallel class:

getExpensiveThing :: Aff (Maybe String)
getExpensiveThing = sequential ado
  mval1 <- parallel fetchLocalStorage
  mval2 <- parallel fetchNetwork
  mval3 <- parallel generateNewBigThingLocally
  in mval1 <|> mval2 <|> mval3

Come to think of it, my snippet above will run all three of those to completion and then return the first Just result, which might also not be what you want. If you want to race those actions and return the first success then you might want to use the Alt ParAff instance, although that’ll require you to represent failure with an exception rather than with Nothing.

1 Like

Ah, but I don’t want it to paralellized … unecessary computations/requests. Maybe do ds fine as it is sequential then? I’m mostly concerned with the unnecessary work while having alt’s <|> short-circuiting the computations while also moving on to the next Aff if it failed.

1 Like

In that case I think you might want to use the Alt (MaybeT Aff) instance, which will only attempt the right hand side if the left hand side finishes with a Nothing result.