that claim seems absurd. all the functional languages I've come across also frequently use routines, modules, and 'objects of whatever' to manage the complexity of huge amounts of code.
objects/entities are just a pattern for hiding complexity behind a simple interface. they can be useful in any language, regardless of mutability.
OOP as a pattern, rather than a language construct.
the great advantage here is that all manipulations are local. there is no spooky action at a distance in an immutable language.
as long as you stay out of the IO monad, anyways.
let rec eventLoop state = let input = getInput () let newState = update input state drawState state; eventLoop newState
The update function takes an existing state and an input record (key events, etc.), returning a new state (which may have nested records within itself but it is all immutable).
New state is kept by the recursion (passing new state to the same function). The only IO is getting input and drawing, which are inherently side-effecting operations.
I do have nested records, but (at each stage) they get joined into a new parent record. No mutability there.
numbers.map(x => x * x)
than let result = [];
for (let i = 0; i < numbers.length; ++i) {
result.push(numbers[i] * numbers[i]);
}For example, what if you now want to write to a log before each multiplication, or you want to time how long each multiplication takes? Suddenly, the latter seems far preferable.
numbers.map(x => {
console.log(x);
return x * x;
})
Still easier to understand than the for loop. for numbers $ \x -> do
Console.log x
return (x * x)It's not enough to just point at an example of a monad and say "look, the example is simple, therefore the generalisation is simple". As many philosophers have pointed out, particulars are easier to point out than universals. The latter requires a lot of thought.
> As many philosophers have pointed out, particulars are easier to point out than universals. The latter requires a lot of thought.
Fair enough, that’s a good point.
You don’t have to use >>= and >> if you don’t want to though. Use the do notation instead and the code will look much more familiar. You also mention fmap; that’s `.map` in Rust, etc. in other languages.
All I’m trying to say is, there are many parallels between Haskell and other languages at the level of particulars. The concepts behind >>= and >> are not unique to it anymore. So there is hope if you want to reconstruct the universal concepts in your mind from those particulars, especially if you use fitting abstractions like the do notation.
Of course there are parallels, there must be for Haskell to be able to do what imperative languages can do. However that doesn't mean the abstractions are simple. "do notation" is another complicated generalisation and there's no way any Haskell programmer it going to be able to simply pretend that their do notation is a normal imperative language.
You seem to be asserting that I'm claiming that Haskell simply can't do the things that imperative languages can do, and I'm not at all and I don't understand how you inferred that.
No, that’s not my intention. I responded to your view that monads are hard to understand by saying that they show up in other languages too in non-trivial ways.
I also don’t mean to say that Haskell is like imperative languages. Just that monads by themselves show up in imperative languages too, so they are not as esoteric as the operator names (>>=, >>) may make them seem.
I appreciate that you followed up in good faith. The point of view that you expressed makes sense to me.
While, when starting with PP or OOP, it is incredibly hard to then learn FP.