I realize my precursory understanding on Monads is severely lacking in detail considering my knowledge comes mostly from Douglas Crockford's Monads and Gonads talk and complicated with my sevear handicap with Haskell (which looks like a bunch of non-alpha numeric characters mushed between disjointed English words to my tragically disadvantaged brain).

With that being said, I'd like to ask about programming practices concerning Monads and how they could be implemented in JavaScript. I'm prefacing this because I recognize that the very nature of the language can drastically affect how one perceives a concept and that because of my background in JavaScript this question could be inappropriate if it were based in a purely functional language like Haskell.

Often times while designing an interface or coding an object I will find myself implementing a form of chaining which mutates the encapsulated data. I prefer this style over more declarative forms like passing in a multi-lined object literal.

function Declarative(options) {
  this.options = options;
}
Declarative.prototype.compute = function() { ... }
var x = new Declarative({
  foo: 'foo',
  bar: 'bar'
});
x.compute();

Verses:

function Chained() { }
Chained.prototype.withFoo = function(v) {
  this.foo = v;
  return this;
};
Chained.prototype.withBar = function(v) {
  this.bar = v;
  return this;
};
Chained.prototype.compute = function() { ... }
var x = new Chained()
  .withFoo('foo')
  .withBar('bar')
  .compute();

Both these examples (aesthetics aside) raise a few hairs on my back because a small voice mockingly squeals "Mutability much?" I begin thinking this might be a good time to conciser a Monad pattern. What I mean by that is each method would in short return a new object of the same type. Then adding composition functions on it like map, bind, etc. could off a world of potential like I get with Promises and other Monad type. (Obviously taking care to follow the three Monadic laws when implemented).

Finally, my other half of the brain starts chiming in with "If all you have is a hammer, everything looks like a nail." Sigh. That is when my productivity and creativity crash here on SE curious and confused.

While I continue my research for understanding (perhaps gaining enough courage to contemplate Haskell) I ask: When does the idea of Monads (that being composability of functions on objects (ie types) along with immutability) become a good idea to be cultivated and patterned? And, when is it nothing more then an over utilized hammer?

(Concepts and learning opportunities welcomed, example code helpful)

有帮助吗?

解决方案

It's hard to tell exactly what you're asking, so this answer is aimed at providing more context about monads. Some preliminaries about monads:

  • Crockford's monad talk is a poor source for learning about monads (I hate to say this because he's so much smarter than me, and therefore probably understand monads better than I do, but IMHO it gives an inaccurate portrayal of monads). So are lots of other monad "tutorials". If you don't put in hard work making your way through real examples, you'll probably never understand monads.

  • monads are neither special nor magical. They can be implemented in many (most? all?) programming languages without special support from the language/runtime/compiler/interpreter. They aren't the end-all, be-all of functional programming. But for some reason, they're what we hear about all the time.

  • monads aren't unique. There are many other related datatypes which are useful in their own right.

  • there are alternatives to monads, depending on what you want/need to do. Search for "effects systems" and "algebraic effects".

  • you can often get most/much of the value of monads without explicitly using them. Just implement the combinators that you need and are useful and use them appropriately. Recognize patterns in your code and factor them out, possibly capturing them as combinators. If some of those combinators happen to match the requirements for unit and join, so be it. That doesn't mean you have to think about what you're doing in terms of monads. (But on the other hand, if you do use monads, you benefit from the numerous combinators already in existence for monads, as well as from writing super-generic code).

When is it inappropriate to use monads?

  • if you have to warp your datatype or the monad laws in order to "make" a monad, you probably shouldn't do that, and should instead ask yourself why you're doing that

  • if your code doesn't benefit from using a monad, or if it actually gets worse (whether because it's longer, or harder to understand, or harder to test, or harder to maintain, ... etc.), you're probably using monads inappropriately

许可以下: CC-BY-SA归因
scroll top