4

I have been looking into the Free monad because I have read that a use case for it is to do logging in a side-effect free way.

I am attempting to do this in JavaScript with the Monet library.

However the documentation is lacking and I do not understand the Free monad well enough figure it out on my own(I have been trying).

I have looked into the Haskell implementation, but I do not read Haskell well and the methods do not appear to be named the same, so I am having trouble.

Any chance someone can give me a simple example of how the Free monad works in either JavaScript or pseudo code that matches the above library?

I feel like if I can see a complete example, I will understand better.

Here are the unit tests from the Monet library: https://github.com/monet/monet.js/blob/develop/test/free-spec.js

But they don't help me much (because they are tests).

Grzegorz Oledzki
  • 23,614
  • 16
  • 68
  • 106
Michael
  • 501
  • 5
  • 12
  • 2
    With a free monad you build up various layers of monadic context, that is no joining takes place. It is your responsibility as a consumer of this structure to define what composition means, or in other words, how to interpret the nested contexts. Also interesting: [Free-er pt1](https://medium.com/@drboolean/free-er-monads-in-js-f5a59e7abc82), [Free-er pt2](https://medium.com/@drboolean/free-er-monads-in-js-pt2-8ab3b9efa510). –  Mar 13 '18 at 20:56
  • 1
    Read this http://degoes.net/articles/modern-fp and https://typelevel.org/cats/datatypes/freemonad.html Sadly, as much in the FP realm, those things are difficult to understand, but when you finally do, you think it's stupidly basic, and yet, you cannot explain it to anyone else... I'll try to make a good explanation in my blog – caeus Mar 15 '18 at 09:23

1 Answers1

0

Doing logging in a side-effect free way is usually done with the Writer Monad:

const compose = (f, g) => value => f(g(value));

const Writer = ({ log = [], value }) => ({
  flatMap: func => {
    const mapped = func(value);

    return Writer({
      log: log.concat(mapped.log),
      value: mapped.value
    });
  },

  log,
  value
});

Writer.of = value => Writer({ value });

Writer.log = entry => value => Writer({ log: [entry], value });

const { log, value } = Writer.of(-42.5)
  .flatMap(compose(Writer.of, Math.abs))
  .flatMap(Writer.log(`abs`))
  .flatMap(compose(Writer.of, Math.floor))
  .flatMap(Writer.log(`floor`));

console.log({ log, value })
David Braun
  • 5,573
  • 3
  • 36
  • 42