Although true; I'm not sure much of that provides clarity. Eg, "Your entire program is ... one new huge instruction" - that is true of any program, and it doesn't sound like a useful abstraction for reasoning about programs. The idea that getChar returns an instruction rather than a character is similarly not an obvious improvement from getChar() returning a character. It is quite subtle for someone to complain that getChar() returning a char is suboptimal.
Everything I've seen is monads are confusing because they solve a problem imperative languages don't think they have. As the article points out,
function getDisplayPictureFromId(id) {
const user = getUser(id)
if (!user) return
const profile = getProfile(user)
if (!profile) return
return getDisplayPicture(profile)
}
is totally fine and idiomatic in most imperative languages. Once a programmer starts chaining functions together (as functional programmers are wont to do) then the "if (!user) return" become a substantial blocker that needs a solution - which leads very quickly to monads and abstracting away IO.
That's not fine and idiomatic in any language I know.
This would be:
function getDisplayPictureFromId(id) {
return getUser(id)?.profile?.displayPicture
}
If the language does not have the null-safe operator '?.' you just write it:
function nullSafe(obj, callback) {
if (obj) {
return callback(obj)
}
return null
}
function getDisplayPictureFromId(id) {
return nullSafe(getUser(id),
(user) => nullSafe(user.profile,
(profile) => profile.displayPicture)
))
}
Not as nice in this case, but with a few similar functions for composing other functions, you achieve similar benefits to Monads without having the complexity of higher-kinded types.
Everything I've seen is monads are confusing because they solve a problem imperative languages don't think they have. As the article points out,
is totally fine and idiomatic in most imperative languages. Once a programmer starts chaining functions together (as functional programmers are wont to do) then the "if (!user) return" become a substantial blocker that needs a solution - which leads very quickly to monads and abstracting away IO.