The difference is in execution: Suspended effects don't execute unless explicitly done through an unsafe function (runBlocking or any of the unsafeIO parts), non-suspended effects execute immeadiatly. This means that a suspend function, and IO, behaves more like a program that produces effects rather than an effect itself, which means a few things: You can replace it with the result and it would work the same (kind of hard since the result is a "program of sorts" (suspended function/IO)) and you can move it around like ordinary values without any weird effects occuring. Being able to replace it with it's result is the most important part for being pure as it allows equational reasoning about code (albeit quite weak, but better than none). For actual usage benefits: You get to treat effectful computations like values, hence you can move them around, discard them at any time, bind ("execute") them at any time and finally replicate/use them as many times as you want. In the case of try: Try, on construction evaluated it's argument, which on it's own is not too bad, except that it's argument had to be impure to be useful. In this case the most common side-effect is throwing exceptions, but nothing stops someone from doing more inside Try. If it's a conscious decision to do side-effects in an unsafe manner in arrow nothings stops it, however we want as few unsafe functions as possible to not accidentally have users write impure (and thus arguably unsafe) code.