functional-programmingpurely-functional

How to perform side-effects in pure functional programming?


I am dealing with the concept of functional programming for a while now and find it quite interesting, fascinating and exciting. Especially the idea of pure functions is awesome, in various terms.

But there is one thing I do not get: How to deal with side-effects when restricting yourself to pure functions.

E.g., if I want to calculate the sum of two numbers, I can write a pure function (in JavaScript):

var add = function (first, second) {
  return first + second;
};

No problem at all. But what if I want to print the result to the console? The task of "printing something to the console" is not pure by definition - but how could / should I deal with this in a pure functional programming language?


Solution

  • There are a few approaches to this. One thing you will just have to accept is that at some point, there exists a magical impure machine that takes pure expressions and makes them impure by interacting with the environment. You are not supposed to ask questions about this magical machine.

    There are two approaches I can think of off the top of my head. There exists at least a third one I have forgotten about.


    I/O Streams

    The approach that is easiest to understand could be streaming I/O. Your main function takes one argument: a stream of things that have happened on the system – this includes keypresses, files on the file system, and so on. Your main function also returns one thing: a stream of things that you want to happen on the system.

    Streams are like lists, mind you, only you can build them one element at a time and the recipient will receive the element as soon as you have built it. Your pure program reads from such a stream, and appends to its own stream when it wants the system to do something.

    The glue that makes all of this work is a magical machine that sits outside of your program, reads from the "request" stream and puts stuff into the "answers" stream. While your program is pure, this magical machine is not.

    The output stream could look like this:

    [print('Hello, world! What is your name?'), input(), create_file('G:\testfile'), create_file('C:\testfile'), write_file(filehandle, 'John')]
    

    and the corresponding input stream would be

    ['John', IOException('There is no drive G:, could not create file!'), filehandle]
    

    See how the input in the out-stream resulted in 'John' appearing in the in-stream? That's the principle.

    Monadic I/O

    Monadic I/O is what Haskell does, and does really well. You can imagine this as building a giant tree of I/O commands with operators to glue them together, and then your main function returns this massive expression to a magical machine that sits outside of your program and executes the commands and performs the operations indicated. This magical machine is impure, while your expression-building program is pure.

    You might want to imagine this command tree looking something like

    main
      |
      +---- Cmd_Print('Hello, world! What is your name?')
      +---- Cmd_WriteFile
               |
               +---- Cmd_Input
               |
               +---+ return validHandle(IOResult_attempt, IOResult_safe)
                   + Cmd_StoreResult Cmd_CreateFile('G:\testfile') IOResult_attempt
                   + Cmd_StoreResult Cmd_CreateFile('C:\testfile') IOResult_safe
    

    The first thing it does is print a greeting. The next thing it does is that it wants to write a file. To be able to write to the file, it first needs to read from the input whatever it's supposed to write to the file. Then it is supposed to have a file handle to write to. It gets this from a function called validHandle that returns the valid handle of two alternatives. This way, you can mix what looks like impure code with what looks like pure code.


    This "explanation" is bordering on asking questions about the magical machine you're not supposed to ask questions about, so I'm going to wrap this up with a few pieces of wisdom.