I actually lost interest, because you are kind of trying to tell me that because of your lack of _familiarity_ with monads, _my_ benefits do not count. I cannot agree with this statement and with this approach.
 
But since there were questions, I'll answer and do some small clarification.

I asked because never tried Eta. So, if you are right, seems no reasons to develop Eta...
I am not sure why you are bringing Eta as an example to this discussion just to point later that you have no experience with it. 
The point of Eta is to run Haskell on JVM. Haskell as of GHC, and not some hypothetical hybrid language (that would be Scala). If you want a decent language, and you must run on JVM then you use Eta. If you don't need to run on JVM - you don't use Eta. 

No better definition then original: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions  You see, they are different.
Now it is your turn to read this link. The second sentence on that link says: 
"They can be used to provide a convenient syntax for monads, a functional programming feature that can be used to manage data, control, and side effects in functional programs."
The emphasis on _monads_ isn't mine, it is original. The computation expressions are _monadic_ (when they obey laws, but that link doesn't say anything about laws, unfortunately).

Something like this:   user?.Phone?.Company?.Name??"missing";     ?
Still no. 

It does not force you to isolate state change in one place with explicit control, it only 
marks place where it happens.

processAttack :: (MonadState s m, HasBpsCounters s) => Attack -> m Result

No benefits for you, tons of benefits for me: I guarantee that this function can only be called if there is access to some BPS counters. I guarantee that this function, and whatever if uses inside itself, can never touch or even look at anything else in my state. I can guarantee that it doesn't cause any other effects like it doesn't call something which calls something which prints to console or writes to DB. And that if during code evolution/refactoring someone does something like that, then it won't compile.

If I add “print” for debug purpose in some subroutines, will they become buggy? No.
Then you add this code inside a transaction and voila - yes, you do have a bug.
In fact, my colleague who used to work at Nasdaq, had a story about exactly this: Once upon a time there was a beautiful code that lived in a transaction. Then someone accidentally introduced a side effect to one of the functions. This function was called from something within that transaction. The bug was noticed after some time when it has done some damage.
In Haskell, you can't do IO in STM, so that wouldn't be possible.

Haskell also does not guard you to mutate this state anywhere in the application.
I think my example above proves otherwise: in Haskell, I can granularly control who can update which part of the state, which makes your statement invalid.

monads have value, but it's small ... their value in other languages is super-small
Again, a VERY bold statement I have to disagree with, once again.
F# workflows are monadic, C# LINQ is precisely modelled by E. Meijer as a list monad. They add great value. 

With this, I rest my case, thanks for the discussion.

Regards,
Alexey.
 
On Mon, Jul 16, 2018 at 5:45 PM PY <aquagnu@gmail.com> wrote:

> So I think if you don't see anybody explicitly mentioning spaghetti
> issues with State that's for some people it's just hiding in plain
> sight and they either aren't consciously aware of it, or find that
> area so self-explaining that they do not think they really need to
> explain that.
>
IMHO State monad solution is orthogonal to my point. It does not force
you to isolate state change in one place with explicit control, it only
marks place where it happens. This info is needed to compiler, not to
me. For me - no benefits. Benefit to me - to isolate changing, but with
State I can (and all of us do it!) smear change points throughout the
code. So, my question is: what exact problem does solve State monad?
Which problem? Mine or compiler? Haskell pure lambda-only-abstraction
limitation? OK, if we imagine another Haskell, similar to  F#, will I
need State monad yet? IMHO - no. My point is: State monad is super, in
Haskell, and absolutely waste in other languages. I will isolate
mutability in another manner: more safe, robust and controllable. Recap:
1. State monad allows you to mark change of THIS state, so you can easy
find where THIS state is changing (tracking changes)
2. Singleton with FSM allows you to *control* change and to isolate all
change logic in one place

1st allows spaghetti, 2nd - does not. 2nd force you to another model:
not changes, but change requests, which can return: "not possible". With
Haskell way the check "possible/not possible" will happen in locations
where you change state in State monad: anywhere. So, my initial point
is: State monad is about Haskell abstraction problems, not about
developer problems.

> Sorry, but that's not what OO is about.
> Also, I do not think that you're using general FSMs, else you'd be
> having transition spaghetti.
To be precise, then yes, you are right. But such model forces me more,
then monadic model. When you create singleton "PlayerBehavior", and have
all setters/getters in this singleton and already check (in one place!)
changes - next step is to switch from checks to explicit FSM - in the
same place. Haskell nothing offers for this. You *can* do it, but monads
don't force you and they are about Haskell problems, not mine.
Motivation of State monad is not to solve problem but to introduce state
mutability in Haskell, this is my point. OK, State monad has helpful
side-effect: allows to track change of concrete THIS state, but I can do
it with my editor, it's more valuable to Haskell itself, then to me,
because no problem to mutate state: Haskell allows it, Haskell also does
not guard you to mutate this state anywhere in the application.

I'm agree with you 100%. My point is related to accents only, my thesis
is: monads have value, but it's small, it's justified in Haskell with
its limitation to one abstraction, but I don't need monads in other
languages, their value in other languages is super-small (if even
exists). So, motivation of monads introduction (for me, sure, I'm very
subjective) is to workaround Haskell model, not to make code more safe,
I'm absolutely sure: monads nothing to do with safety. It's like to use
aspirin with serious medical problem :)

> Let me repeat: What you call a "message" is just a standard
> synchronous function call. The one difference is that the caller
> allows the target type to influence what function gets actually
> called, and while that's powerful it's quite far from what people
> assume if you throw that "message" terminology around.
I mentioned Erlang early: the same - you send message to FSM which will
be lightweight process. Idea of agents and messages is the same in
Smalltalk, in QNX, in Erlang, etc, etc... So, "message" does not always
mean "synchronous call". For example, QNX "optimizes" local messages, so
they are more lightweight in comparison with remotely messages (which
are naturally asynchronous). But "message" abstraction is the same and
is more high-level then synchronous/asynchronous dichotomy. It allows
you to isolate logic - this is the point. Haskell nothing to do with it:
you smear logic anywhere. But now you mark it explicitly. And you have
illusion that your code is more safe.

> But that's not the point. The point is that Haskell makes it easy to
> write non-spaghetti.

How? In Haskell I propagate data to a lot of functions (as argument or
as hidden argument - in some monad), but with singleton+FSM - you can
not do it - data is hidden for you, you can only *call logic*, not
*access data*. Logic in Haskell is forced to be smeared between a lot of
functions. You *CAN* avoid it, but Haskell does not force you.

> BTW you have similar claims about FSMs. Ordinarily they are spaghetti
> incarnate, but you say they work quite beautifully if done right.
> (I'm staying sceptical because your arguments in that direction didn't
> make sense to me, but that might be because I'm lacking background
> information, and filling in these gaps is really too far off-topic to
> be of interest.)

I respect your position. Everybody has different experience, and this is
basically very good!

> We often repeat this: “side-effects”, “tracks”, “safe”. But what does
> it actually mean? Can I have side-effects in Haskell? Yes. Can I mix
> side-effects? Yes. But in more difficult way than in ML or F#, for
> example. What is the benefit?
>
> That it is difficult to accidentally introduce side effects.
> Or, rather, the problems of side effects. Formally, no Haskell program
> can have a side effect (unless using UnsafeIO or FFI, but that's not
> what we're talking about here).

Actually if we look to this from high-level, as to "black box" - we see
that it's truth. Haskell allows to have them, to mix them but in
different manner.

> Yes they will. Some tests will fail if they expect specific output. If
> the program has a text-based user interface, it will become unusable.

And wise-versa: if I will remove "print" from such tests and add "pure"
- they can fail too. IMHO purity/impurity in your example is related to
expected behavior and it violation, not to point that "more pure - less
bugs". Pure function can violate its contract as well as impure.

> Yes they will become buggy. You'll get aliasing issues. And these are
> the nastiest thing to debug because they will hit you if and only if
> the program is so large that you don't know all the data flows
> anymore, and your assumptions about what might be an alias start to
> fall down. Or not you but maybe the new coworker who doesn't yet know
> all the parts of the program.
> That's exactly why data flow is being pushed to being explicit.

So, to avoid this I should not mix read/write monads, to avoid RWST. In
this case they should be removed from the language. And monad
transformers too. My point is: there is some misunderstanding - I often
listen "side-effects are related to errors", "we should avoid them",
"they leads to errors", etc, etc, but IMHO pure/impure is needed to FP
language compiler, not to me. This is the real motto. Adding of
side-effects does not lead to bugs automatically. Mostly it does not.
More correct is to say: distinguish of pure/impure code is better to
analyze the code, to manipulate with it, to transform it (as programmer
I can transform F# code *easy because no monads*, in Haskell *compiler*
can transform code easy *because monads*). More important argument for
me is example with Free monads. They allows to simulate behavior, to
check logic without to involve real external actions (side-effects).
Yes, OK, this is argument. It's not explicitly related to buggy code,
but it's useful. It remember me homoiconic Lisp code where code can be
processed as data, as AST.

Actually, I had a big interesting discussion in my company with people
which does not like FP (the root why I become to ask such questions to
himself). And I got their arguments. I tried to find solid base of mine.
But currently I see that I like Haskell solutions itself, and I can not
show concrete examples where they are needed in real world, without
Haskell specific limitations. I know that those limitations lead to slow
compilation, to big and complex compiler, I can not prove that
side-effects means "lead to error", or (more interesting) that it's bad
to separate side-effects from each other. F#, ML, Lisps have "do-" block
and no problem with it. They don't need transformers to mix 2 different
effects in one do-block. If you can prove that this decision leads to
bugs and Haskell solution does not: it will be bomb :) I think, will be
a lot of people in CS which will not agree with you ever.

---
Best regards, Paul

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.