Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functional programming construct for composing identity and side effect

Does functional programming have a standard construct for this logic?

const passAround = (f) => (x) => {
  f(x);

  return x;
};

This enables me to compose functions that have side effects and no return values, like console.log. It's not like a Task because I don't want to represent the state of the side effect.

like image 373
maxhallinan Avatar asked Sep 08 '17 12:09

maxhallinan


1 Answers

If you are talking about pure functional programming, then you need to challenge this starting point:

functions that have side effects and no return values

In functional programming, there is no such thing. Every function is defined as a transformation on some input into some output.

So the obvious question is, how would you represent console.log without a side effect? To answer, we need to challenge another assumption in your question:

I don't want to represent the state of the side effect

This is exactly how functional programming represents the problem: consider your input and output to be "the state of the world". In other words, given the state of the world before the function, return the state of the world after the function. In this case, you would be representing the state of the console: given a console with x lines of output, return a console with x+1 lines of output. Crudely, you could write something like this:

(x, console) => { return [x, console.withExtraLine(x)]; }

The more powerful mechanism generally used for representing this is called a "monad" - a special kind of object which wraps a series of steps along with some extra meaning. In the case of the IO monad, each step is wrapped with an action which will transform the state of the world. (I/O is just one of many useful applications of the monad concept.)

You write the steps as functions which only know about the "unwrapped" value of some part of that state (e.g. a parameter which ultimately came from user input), and the monad handles the messy details of actually executing that outside the realm of the functional program. So rather than thinking about your input and output as "the state of the world", you think about your input as "a chain of computations", and your output as "a slightly longer chain of computations".

There are many introductions to this that are far better than any I could give, just search for "monad" or "functional programming io".

See also, this answer, this question, and probably many others in the "Related" sidebar auto-generated when you view this question.

like image 186
IMSoP Avatar answered Sep 20 '22 18:09

IMSoP