Isn’t a monad just a monoid in the category of endofunctors?
Comment on What programming languages aren't too criticized here?
ishanpage@programming.dev 1 year agoUnfortunately, no one can be told what a monad is. You have to see it for yourself (then you won’t be able to explain it to anyone)
FooBarrington@lemmy.world 1 year ago
shagie@programming.dev 1 year ago
The Codeless Code : Monolith thecodelesscode.com/case/143
On the topic of Monads: thecodelesscode.com/topics/monads (though the other one really needs you to read the rest of the site to get a better understanding of the monk Djishin and the Java Master Banzen … and remember there’s css hidden topics along with image mouse overs… in case you read the first hundred and then realize that there’s more to each one and have to go back and read them all again).
ishanpage@programming.dev 1 year ago
Ohhhh, this site is a great find. Exploring all the articles right now. Thanks!
alr@programming.dev 1 year ago
If you use JavaScript, you’ve probably seen a monad, since Promise is a monad. Unit is
Promise.resolve()
, bind isPromise.then()
. As required,Promise.resolve(x).then(y) === y(x)
(unit forms a left identity of bind),y.then(Promise.resolve) === y
(unit forms a right identity of bind), andx.then(y.then(z)) === x.then(y).then(z)
(bind is essentially associative).
angryzor@programming.dev 1 year ago
The problem is people constantly try to explain it using some kind of real world comparison to make it easier to visualize (“it’s a value in a context”, “it encodes side effects”, “it’s just flatmap”, “it’s a burrito”), when all it really is is an abstraction. A very, very general abstraction that still turns out to be very useful, which is why we gave it the cryptic name “monad” because it’s difficult to find a name for it that can be linked to something concrete simply because of how abstract it is. It really is just an interface with 2 key functions: (for a monad M)
Anything that you can possibly find a set functions for that fit this interface and adheres to the rules described by someone else in this thread is a monad. And it’s useful because, just like any other abstraction, if you identify that this pattern can apply to your type M and you implement the interface, then suddenly a ton of operations that work for any monad will also work for your type. One example is the coroutine transformation (async/await) that is an extremely popular solution to the Node.JS “callback hell” problem that used to exist, and which we call do-notation in Haskell:
This is a transformation you can actually do with any monad. In this case
Promise.resolve
is an implementation ofwrap
, andthen
is an implementation ofbind
(more or less, it slightly degenerate due to accepting unwrapped return values from f). Sadly it was not implemented generally in JS and they only implemented the transform specifically for Promises. You may have noticed that generators with “yield” syntax are very similar to async/await. That’s because it’s the exact same transformation for another specific monad, namely generators. It’s sad because many people say they hate monads because they’re complex, but then heap praise on Promises and async/await which is just one limited implementation of a monad. List comprehensions are another common implementation where this transform is useful:Another (slightly broken) implementation of monads and the coroutine transform people use without knowing it is “hooks” in the React framework (though they refuse to admit it in order to not confuse beginners).</u></u>
angryzor@programming.dev 1 year ago
Thought I’d finish the Monad Tutorial since I stopped midway…
The general notion that the abstraction actually captures is the notion of dependency, the idea that an instance x of your type can be in some common operation dependent on other instances of your type. This common operation is captured in
bind
. For Promises for example, the common operation is “resolving”. In my first post, for thegetPostAuthorName
promise to resolve, you first need to resolvegetPost
, and then you need to resolvegetUser
.It also captures the idea that the set of dependencies your x is not fixed, but can be dynamically extended based on the result of the operation on previous dependencies, e.g.:
In this case,
getPostAuthorName
is not dependent ongetUser
ifgetPost
already resolved to undefined. This naturally induces an extra order in your dependents. While some are independent and could theoretically be processed in parallel, the mere existence of others is dependent on each other and they cannot be processed in parallel. Thus the abstraction inherently induces a notion of sequentiality.An even more general sister of Monad, Applicative, does away with this second notion of a dynamic set and requires the set of dependents to be fixed. This loses some programmer flexibility, but gains the ability to process all dependents in parallel.