Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Monads are considered pure?

I am very much new to Haskell, and really impressed by the language's "architecture", but it still bothers me how monads can be pure.

As you have any sequence of instructions, it makes it an impure function, especially functions with I/O wouldn't be pure from any point of view.

Is it because Haskell assumes, like all pure functions, that IO function has a return value too, but in form of opcode or something? I am really confused.

like image 722
lycuid Avatar asked Sep 11 '16 16:09

lycuid


2 Answers

One way to think of this is that a value of type IO a is a "recipe", containing a list of instructions that if performed would have side effects. Constructing that "recipe" though, does not have any side effects. So a haskell program (whose type is IO ()) is basically a computation that constructs such a recipe. Importantly, the program does not execute any of the instructions in the recipe. When the recipe is completed the program terminates. Then the compiler (or interpreter) takes that recipe and executes it. But the code that the programmer wrote is not running anymore, so the instructions in the recipe are executed outside the scope of the program.

like image 141
redneb Avatar answered Oct 10 '22 09:10

redneb


One way that "monads can be pure" is that they can represent pure expressions. I.e. in the List monad this:

do x <- xs
   return (x+1)

is the same as map (+1) xs.

Another way you can say "monads can be pure" is that Haskell distinguishes between creating a monadic computation and running the computation.

Creating a monadic computation is pure and doesn't involve any side effects. For instance, replicateM 3 foo will perform foo three times as in replicateM 3 (putStrLn "Hello, world"). Purity allows us to reason that replicateM 3 foo is the same as do { foo; foo; foo }. Note that this is true regardless of what kind of computation foo is - it could be a pure computation or one that involves some sort of effect.

Side effects only happen when you run the monadic computation. In the case of the IO monad this happens at run-time time when main is executed. Other monads have their own "run" functions, i.e. runReader for the Reader monad, runState for the State monad, etc.

like image 30
ErikR Avatar answered Oct 10 '22 08:10

ErikR