Oh, haven't seen a monad article in quite some time.<p>> Monads really are just a convenient way to build up action values<p>Except when they aren't, because lists/arrays (with map) and Maybe (with map) and .. are something totally different. And that's the problem with _all_ these monad tutorials/how-tos/...: the problem is, that monads (and functors) are not burritos or elephants but _both_. So they are hard to understand looking only at a single instance.<p>Btw. monads are not the only way FP deals with effects, see algebraic effects.
<a href="https://github.com/yallop/effects-bibliography" rel="nofollow">https://github.com/yallop/effects-bibliography</a>
<a href="https://www.youtube.com/watch?v=DNp3ifNpgPM" rel="nofollow">https://www.youtube.com/watch?v=DNp3ifNpgPM</a>
So this is basically Eternalism[1]? Instead of writing a program that reads inputs, experiences a sequence of state mutations and takes actions, you generate the graph of every possible state and path between states annotated with inputs on the edges and outputs on the vertices, and let the runtime pick the actual path through it. And this works because you're generating it lazily, but that's just an implementation detail. And the program in itself isn't ever in any particular state, because the program is the description of every possible state.<p>[1] <a href="https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time)" rel="nofollow">https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time...</a>
I don't speak Rust well, but I can share my perspective from Clojure, where I tend to think in data.
A program is a sequence of immutable functions taking input from the world and reducing that to instructions to mutate the world (aka side effects). The world here can also be some place that stores state.
Ideally mutation is the last step of the pipeline, which takes the instructions and produces the side effects.<p>Or simply<p>input -> fn1 -> fn2 -> fnn -> mutate!<p>Where 'fn' are all immutable.
Well, that's the first time side effects in Haskell made sense to me. Well done.<p>Not that I've ever <i>seriously</i> tried to learn Haskell, but in the past every time I've lazily come across an article about it it's always seemed like a bizarre confusing world, even though I know how functional programming (in the sense of purity) works.<p>Now there's just one thing missing. We all know what this style of programming is. It's asynchronous programming with callbacks. Seriously, Haskell folks, if you started with "all side effecting functions are kind of like async operations with a completion callback (the stuff people do in JavaScript all day), and then we have some syntactic sugar to make it suck less" you'd have a <i>much</i> easier time getting people to wrap their head around all this.<p>(Yes, I know the details aren't exactly the same, but drawing parallels to stuff people already know matters)<p>Seriously, this idea of there being a central effect dispatcher (the bit that runs `main` behind the scenes) is so eerily like the coroutine scheduler in async coroutine paradigms that I can't believe more people haven't drawn parallels between these programming styles.
The author doesn't mention laziness, which is pretty huge. Laziness is half of immutable data structures!<p>I have a tidbit in the first paragraphs: <a href="http://blog.vmchale.com/article/effects" rel="nofollow">http://blog.vmchale.com/article/effects</a>
> I don't know why people try to explain monads without explaining this first<p>I mean, I get where you're coming from, but the thing that you've described is that a monad and there's not an easy way to get it there.<p>But yes, I am with you, you want to explain to someone that Haskell's model of side effects is a sort of <i>metaprogramming</i>, much simpler than macros, we just give you a data type for “a program which does some stuff and eventually can produce a ______” and ask you to define a value called `main` which is a program which produces nothing special. And it's the compiler's job to take that program and give it to you as a binary executable that you can run whenever you like.<p>You also want to give people a number of other examples of things that are monads. “a nullable ____”, “a list of ____s,” “an int (summable) with a ____,” and maybe an example that is not like “a
function from ____s to ints,” or “a set of ___s.”<p>The key to telling someone what a monad is, involves trying to explain to them that in some sense “a program which produces a program which produces an int” is not terribly more descriptive than just “a program which produces an int.” If you can combine this with the adjective being outputtish and universal you have a monad.
As someone who has never really understood monads (or tried that hard to) but who has done a good amount of Javascript programming, I really like the description of a monad as a series of nested data structures describing the next steps of a project.<p>Ultimately, that's very similar to what old-school ways of declaring Promises do in Javascript. You're creating a data structure that you then attach a new function to execute with the results.
Haskell is a framework that takes a monad interface implementation and performs IO based on it. The monad in question is used like a self flattening iterator / generator, and together with lazy evaluation it can function like a regular program even though the monad itself is implemented using pure functions.
One benefit of describing state change as a pure data structure, instead of directly executing it, is that you may now write functions that run these state changes in different ways.<p>E.g. you may have a dry-run function that doesn't actually change the state but only describes what it would do. Or you could have a function that generates a verbose log of all steps executed. Etc.<p>That doesn't necessarily work for IO, as that gets special treatment by the runtime, but you can do it with your own types.
Something that I always found funny is that main clearly has to take something as input (otherwise it would not be able to produce different output between runs). So in GHC the main method (main :: IO()) internally takes a value of type RealWorld (theRealWorld) and returns the new RealWorld produced by running the program. I imagine by the time it's lowered to actual assembly they've dropped that, but I've never dealt with ghc's machine codegen
"How to do side effects in s/FP/Haskell"<p>Erlang is a functional programming language and doesn't need to jump through hoops to do side effects.<p>So is OCaml. So is...
dweb link:<p>> ipfs resolve -r /ipns/nauseam.eth/coding/random/how-side-effects-work-in-fp/: no link named "coding" under QmdzzonFE9eX6FGs8UbCyoC2XS5NQjaG6gaqhgeUyTHnag
> You're viewing my site on the centralized web. Check me out on the dweb ! (Warning: it's slow.)<p>It's really hard to take someone serious when they make big, untrue, statements saying the real web is "centralized" right on every page of their site, to peddle crypto scams.<p><a href="https://chadnauseam.com/reasoning-quiz" rel="nofollow">https://chadnauseam.com/reasoning-quiz</a><p>> Neo-Nazis are holding a demonstration in a small town, waving swastikas around and shouting about Hitler. They seem to be pretty peaceful so far, so the First Amendment says you probably can’t get rid of them. However, their demonstration is near a main street and it could be a minor inconvenience to the traffic trying to go through.<p>><p>> [ ] Allow the neo-Nazis to demonstrate.<p>><p>> [ ] Break up the demonstration on the grounds of ‘blocking traffic’.<p>I am at a loss for words. Nazi sympathy under the guise of tolerance.
FP explanations like this annoy me:<p>That is, this code:<p>x = foo()<p>y = bar(x)<p>z = bar(x)<p>Should mean the same thing as:<p>y = bar(foo())<p>z = bar(foo())<p>Because it's obvious to anyone that has written any sort of complex program that those are not the same thing. foo() can be an expensive operation like an HTTP call. Or it might depend on a database which can change state underneath it.<p>I assume FP has answers for these things but the tutorials never cover them. They all imagine a world without state or expensive operations to show how wonderful it is. And that's an easy world to program in.