Can I always replace a do-block like this:
do
...
pure ...
where the last line is "pure" something, with an ado-block like this:
ado
...
in ...
?
I know do only requires Bind and not Monad (i.e. Applicative), but we're already using pure so we're already Applicative.
The long answer
The difference between Applicative (and therefore applicative do -
ado) and Monad (bindordo) is that when combining two applicative computations, the second one cannot depend on the result of the first computation. This means:But if y depends on x we cannot do that:
This means the answer to your question is "no".
Examples
Let's think about an intuitive example. The Aff Monad allows us to run asynchronous effects, like fetching data from an API. If the requests are independent, we can run them in parallel.
If they depend on each other, we need to run one request after another:
Please note, that
Affalways runs things sequentially no matter if you usebindorapply, unless we useparallelwhich turns anAffinto aParAff. Notice the lack of a Bind/Monad instance forParAffbecause two parallel computations cannot depend on each others results! https://pursuit.purescript.org/packages/purescript-aff/7.1.0/docs/Effect.Aff#t:ParAffMeaning for the first example to really run in parallel, we have to actually
Another example I like is parsing/validation. Imagine you are parsing two fields of user input: A date string and an age. We can check both properties an parallel and return two errors if both properties are invalid. But to validate a date, we might first have to check if an input value is a string and then check if the value is a date string. For an example library, check out purescript-foreign
We see that Applicative is much weaker than Monad. But there are intances, where forgoing in the power of Monad can give us other interesting possibilities like parallelisation or multiple errors.