Can a monad be thought of as a function that accepts a value and wraps it such that it meets specific interface and behavioral constraints that have been found to be useful when working in a functional style?
No. The function that wraps a value is unit.
If you're trying to see if it makes sense to explain monads as a unit function that returns an object with a bind method that follows the monad laws, it doesn't quite work. The problem is that there are monadic values that can't be created with the unit function.
For example, in the Maybe monad, the Nothing value can't be created with unit, and the whole point of the existence of the Maybe monad is to allow for the Nothing value.
In general, monadic values created by the unit function are simple and boring and plain, and don't illustrate why we wanted to have whatever monad we're dealing with in the first place. Unit is great for turning plain values into monadic values and plain functions into monadic functions for compatibility, but that's it.
After thinking about it for a bit, I was actually able to work out a proof on paper that all useful monads have monadic values that cannot be created by unit. (Specifically, either there is only one monadic value in the monad (which is useless), or the monad is isomorphic to the identity monad (which is useless in the same way the identity function is useless), or the monad has monadic values that can't be created by unit.)
This is wrong
Monad(x).bind(function(x){return x;}) == Monad(x); // for all x
it should be
unit(x) == function(x){return Monad(x);} // I'm assuming this is what you mean by Monad(x)
Mx.bind(unit) == Mx; // for all monadic values Mx
This
Monad(x).bind(fn) == Monad(fn(x)); // for all x, fn
should be
Monad(x).bind(fn) == fn(x); // for all values x and monadic functions fn
You can bind with any monadic function, which is a function of one argument that returns a monadic value of the same type that the implementation of bind works on, but you can't bind with all functions.
This is wrong
Monad(x).bind(fn1).bind(fn2) == Monad(x).bind(function(x) {
return fn2(fn1(x));
});
it should be this
// for any monadic value Mx and any 2 monadic functions fn1 and fn2 whose types line up
Mx.bind(fn1).bind(fn2) == Mx.bind(function(x) {
return fn1(x).bind(fn2);
});
iii. It has a "bind" method that takes a monad, a function that takes a some type and returns a monad (is this another monad?), and returns a monad.
You're using the word monad to mean several different things, which I think is fine, but is potentially unclear to people who haven't wrapped their heads around monads yet. There are three things you could mean by monad: the general pattern of monads/monads in general, a specific monad, or a monadic value. Monads in general are what you're trying to define/explain, a specific monad would be a particular instance of this general pattern/interface (like the Maybe monad or the List monad), and a monadic value is a value of the type that unit or bind output (like the list [1,2,3]
for the list monad).
So we can simplify that to
iii. It has a "bind" method that takes a monadic value and a monadic function and returns a monadic value.
Although that doesn't make clear that bind doesn't work between different monads or that the type of the output of the monadic function is the same as the type of the output of the bind.
Another way to look at bind is as a monadic equivalent of function application. Plain function application takes a plain value and a plain function and returns a plain value. Monadic binding takes a monadic value and a monadic function and returns a monadic value. If you've got a monadic value Mx
and a monadic function fn
, you can't do fn(Mx)
, because fn
doesn't work on monadic values. But you can do Mx.bind(fn)
.
i. It has a type constructor that defines its type (What is this?).
A type constructor is a concept that exists in Haskell, but doesn't really in javascript. I'm not sure of the best way to go about talking about this in javascript, but I'd probably end up talking about Classes, because even though they don't really exist in javascript, javascript programmers know what that concept is. For any monad, there has to be a definition of what monadic value means for that particular monad, and that's what goes here.