1. Each IO operation returns a special value which denotes an IO action
2. These IO actions can be sequenced using a function which feeds an IO action to a continuation
3. Syntax sugar to remove the annoyance of explicitly writing the sequencing function
Together, (1) and (2) make this a monad; (3) in this article is just ‘do’-notation. The only major difference from Haskell is that Roc doesn’t generalise the idea to other monads, which makes it far less powerful than Haskell’s Monad typeclass.