# What's the value of IO Monad?

When I'm writing code in the form of IO Monad, I wonder what's real value of it.For example I have a function as `def something(in: In): IO[Out]`; my function is a `pure function` that **returns an impure recepie(just another function) which could be composed with other receipes, and finally triggered.

Is postponing the side-effects the best I get? In other words, what's the difference in the value between a function with side-effects, and a pure function which return an impure function? In my eyes both approches could be testable, trackable, debugable (the IO version could be harder, as stacktraces are not as helpful as simple stack-calls).

• One way to look at it is as a form of layering. The IO Monad encapsulates the "impure world", and represents side effects (the various possible impure recipes) as abstract values (literally think of monadic values as opaque points (elements) in some mathematical set). Then the upper layer can maintain purity by working with these abstractions. In a sense, the upper layer doesn't really "know" that each recipe is "just another function", it just treats them as these abstract values. Jun 28, 2020 at 21:01
• A monad isn't "impure". Consider it as an abstract reference to a value that can be passed to a pure function that you give it using the bind function. That way, everything can be pure (functions have no direct side effects and are always referentially transparent) without preventing useful operations. Jun 30, 2020 at 12:20
• The IO Monad is the reason you can have a language where functions don't have side effects. If you didn't have the IO monad, you'd have to let functions have side effects, and then instead of Haskell, you'd have Python with different syntax. Jun 30, 2020 at 18:01

In addition to what Jacques said about the side effects being explicit in your type system, you also get referentially transparent side effects. This means you can store effects or groups of effects in variables and lists and end up with the exact same result. The cats State documentation has a good example of this for the State monad.

One thing this enables that isn't immediately apparent how useful it is, is the order you specify your effects can be different from the order they execute, and some you specify may not end up executing at all.

Let's say you have a request that connects to a list of servers, does some processing, and returns the first successful result. The request contains all the information needed to do the processing step, so you specify that effect first. The list of servers is read from config, so that's handled somewhere else, perhaps memoized. You can specify all the effects for connecting to the servers in one place, but then later choose to run them one at a time, or in parallel, or with retries.

In other words, it makes it a lot easier to separate the concerns of what gets executed from what order it gets executed.

• This is an excellent and intuitive explanation, one of the best I’ve seen so far Nov 9, 2021 at 23:19

The primary benefit is you get the `IO` explicitly in the type of the function. So you know that any function without `IO` in the signature is side-effect free. The pure parts of the program is guaranteed to be pure and side-effect free by the type system.

• Even functions with `IO` are side effect free. They are functions which return values which describe side effects. You can do `let x = putStrLn "hello world!"` all day and it won't print anything. Jun 30, 2020 at 18:00
• @user253751: No, this is just defining a function, not executing it. Same as in e.g. JavaScript you can write `let x = () => console.log('Hello world');` which does not have any side effect either, because it is just defining a function, not executing it. Dec 1, 2021 at 13:49
• A function is a mapping from values to other values. `IO` values are not those. Dec 1, 2021 at 14:19