@@ -188,82 +188,21 @@ If the value is fetched, input, received, selected, than use ``IO`` container.
188188
189189Most web applications are just covered with ``IO ``.
190190
191- What is the difference between IO[Result[A, B]] and Result[IO[A], B] ?
192- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
191+ Why IO should be at the top level of composition ?
192+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
193193
194194As we state in :ref: `Composition docs <composition >`
195195we allow to compose different containers together.
196196
197- That's where this question raises:
198- should I apply ``IO `` to all ``Result `` or only to the value part?
199-
200- Short answer: we prefer ``IO[Result[A, B]] ``
197+ We prefer ``IO[Result[A, B]] ``
201198and sticking to the single version allows better composition.
199+ The same rule is applied to ``Maybe `` and all other containers we have.
202200
203- Long answer. Let's see these two examples:
204-
205- .. code :: python
206-
207- from returns.io import IO , impure
208- from returns.result import Result, safe
209-
210- def get_user_age () -> Result[IO [int ], ValueError ]:
211- # Safe, but impure operation:
212- prompt: IO [str ] = impure(input )(" What's your age?" )
213-
214- # Pure, but unsafe operation:
215- return safe(int )(prompt)
216-
217- In this case we return ``Result[IO[int], ValueError] ``,
218- since ``IO `` operation is safe and cannot throw.
219-
220- .. code :: python
221-
222- import requests
223- from returns.io import IO , impure
224- from returns.result import Result, safe
225-
226- @impure
227- @safe
228- def get_user_age () -> IO [Result[int , Exception ]]:
229- # We ask another micro-service, it is impure and can fail:
230- return requests.get(' https://...' ).json()
231-
232- In this case the whole result is marked as impure.
233- Since its failures are impure as well.
234-
235- What is the difference between IO[Maybe[A]] and Maybe[IO[A]]?
236- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237-
238- The similar question is about ``IO `` and ``Maybe `` composition.
239- Let's illustrate it with the code example:
240-
241- .. code :: python
242-
243- from returns.maybe import Maybe, Nothing
244- from returns.io import IO
245-
246- def maybe_ask_user (should_ask : bool ) -> Maybe[IO [str ]]:
247- if should_ask:
248- return Maybe.new(IO(input (' Asking!' )))
249- return Nothing
250-
251- In this example ``IO `` might not happen at all.
252-
253- .. code :: python
254-
255- from returns.maybe import Maybe, Nothing
256- from returns.io import IO
257-
258- def ask_user () -> IO [Maybe[str ]]:
259- prompt = input (' Asking!' )
260- if prompt:
261- return Maybe.new(IO(prompt))
262- return IO(Nothing)
201+ Composing ``IO `` at the top level is easier
202+ because you can ``join `` things easily.
263203
264- In this second case, we always do ``IO ``, but we return ``Nothing ``
265- if user inputs an empty string
266- (because we need this business logic for some reason).
204+ And other containers not always make sense.
205+ If some operation performs ``IO `` it should mark all internals.
267206
268207Why can't we unwrap values or use @pipeline with IO?
269208~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0 commit comments