6 ms·
Monad is a thingie that lets you sequence computations in the same context. Context being something like Future or Stream or List
by AzzieElbab 5y ago
Monad is a thingie that lets you sequence computations in the same context. Context being something like Future or Stream or List
- kayodelycaon 5y agoI’m not sure if this is supposed to be sarcastic or not but it doesn’t make any more sense to me.
- chii 5y agoit doesn't make sense to an imperative programmer because "sequence computations" is like water to a fish. the idea that computation isn't always sequenced doesn't occur to someone who hasn't encountered functional programming.
- kayodelycaon 5y agoNot sure what you mean by that. Threaded and event-driven systems don’t necessarily have a predictable sequence. Same with data flow through any non-trivial web application using background processing. I’ve worked on systems that run through a chain of background workers. Each job had a complete list of operations (one per worker) to preform. When each worker finished, it posted the job back to the general queue with the new state and one less operation to preform. All programs are eventually sequenced. You can’t work on data that doesn’t exist yet. I’m pretty sure I don’t lack the ability to understand what your talking about. I am sure I don’t know what the words you are using mean.
- ModernMech 5y agoAs an educator, I get to see many young programmers learn about functional programming usually around their sophomore year of college. They've never used threaded, event-driven, dataflow, or similar systems. All they know how to write are single-threaded Java programs, and their perception is that programs are "a list of statements that tell a computer what to do, in order". They are especially uneasy about the concept of lazy evaluation. It goes against everything they know about programming - that you write a line of code, it's executed, and you move on to the next line of code. With lazy evaluation (as in Haskell) it's an uphill battle getting them comfortable with the idea of writing a line of code that will be executed at some unspecified point in the future. For many students, this can be a mind-bending realization.
- deltasixeight 5y agoIt's just something to know, nobody is actually keeping track of when logic is actually executed.
- deltasixeight 5y agoLet me just explain to you what functional programming is at a high level and I'll get a little bit into the monad. Maybe that will help you understand. IF you can compress all your javascript into one line of code or as close to it as much as possible then you are absolutely doing functional programming. That is essentially what functional programming is, how to program so everything goes on one line. You can think of it as expression based programming, or how to compress your entire program into a single expression! Now, when you see multiline functional code, what's actually happening is that the programmer is giving parts of his expression a name and placing it on another line so that the code is more readable or the programmer could be generalizing logic in the expression for reuse in other places. Example: addOneTime8PlusTwoMinusThreeTimes300 = (x) => (x + 1 * 8) + 2 - 3 * 300 is made into addOneTimes8 = function(x) => x + 1 * 8 plusTwoMinusThreeTimes300 = function(x) => 2 - 3 * 300 addOneTime8PlusTwoMinusThreeTimes300 = (x) => plusTwoMinusThreeTimes300(addOneTimes8(x)) That's it! Turns out that doing this type of organization is EXACTLY the same as doing procedural programming with one extra property! Keeping everything immutable! So if you program in javascript and you keep everything immutable you are doing the exact same thing as compressing all your code onto a single line! Now that being said there's a lot of this going on in functional programming: addOneTime8PlusTwoMinusThreeTimes300 = function(x) => Times300(MinusThree(PlusTwo(Times8(addOne(x))))) and to make things more easier to read people have special syntax to write it like this: addOneTime8PlusTwoMinusThreeTimes300 = function(x) => ( addOne | Times8 | PlusTwo | MinusThree )(x) The above is literally the same thing as operator overloading you just define the operator to be: f | y = function(x) => f(y(x)) and you use it as such: ( f | a | b | x )(x) like bash kinda. This type of thing is called function composition! A monad is just a special type of composition Not only do I want to compose all the functions but at each step of the composition I want to do an extra thing! So let's say I want to log the output So I define f | y = (x) => { result = y(x) print(result) return f(result) } Then when I compose: ( f | a | b | x )(x) It will print out each intermediary value along the pipeline! That is essentially one type of monad. A monad is a way to compose functions such that they do an extra thing! And this intuition probably takes you 85% of the way there on how to use monads in haskell. Monads in haskell just have some extra rules but the intuition is 100% the same thing. Now you will note that I cheated for f | y. I wrote the code on multiple lines! That is exactly what "sequential" code is! It is the fundamental property of reality that is at odds with functional programming. Haskell is trying to get rid code that requires you to write things on multiple lines! It is trying to abstract all of that away with a bunch of crazy abstractions so all your code can fit beautifully onto a single line! It is in fact impossible to write the multi line code I wrote above in haskell. What haskell does is present to you the IO monad as an API so you print things through composition and you never have to write "sequential" lines of code. Turns out when you do single line coding a whole class of errors disappears and your code is also far more modular. It's hard to convince you of the benefits with just words. If you want to know more, you have to walk the path, I can only show you the way. One more thing. When code is written this way the compiler can do much more tricks with it. Because state is immutable the compiler can execute code in a different order to achieve the same result as your intention. You don't have to often think about this when programming in haskell but it does allow you to do certain tricks.
- yudlejoza 5y agoOne way to think of a monad is through the example of a shell (e.g., bash) pipeline: # cat data.csv | process-1 | process-2 | ... | process-n > final-output Imagine you have this pipeline that already works for data.csv. But now you have data2.csv which has some difference (e.g., some values are null, while the original data.csv had no null values). Monads are an approach to making the existing pipeline work (with minimal changes) while still being able to handle both data.csv and data2.csv. The minimal changes follow a strict rule as follows (this is not a valid shell command anymore): # wrap(cat data.csv) ] process-1 ] process-2 ] ... ] process-n > final-output In other words, only two kinds of changes are allowed: - You can bring in a wrap function, that modifies the entries of the given csv data. - You can bring in a new kind of pipe ']' instead of '|' The idea being, the wrap function takes in original data stream, and for each "unit" (a line in the csv file, called a value) produces a new kind of data-unit (called monadic-value). Then your new pipe ']' has some additional functionality that is aware of the new kind of data-unit and is able to, e.g., process the null values, while leaving the non-null values unchanged. Note, you didn't have to modify any of the process-1 through process-n commands. BTW, the null value handling monad is called the 'maybe monad' (and of course there are other kinds of monads). If you make the existing pipeline work in this way, you essentially created a monad to solve your problem (monad here is the new mechanism consisting of the new value, and the two new changes, the wrap function, and the new pipe). edit: There may be a need to also modify the '>' mechanism. But I think that is not essential to the idea of a monad, since you could replace ">" with "] process-n+1 >" (i.e., you created a new outermost function 'process-n+1' that simply converts the monadic-values back to regular values). edit 2: If instead of handling null-values, the purpose is to "create side-effects" e.g., at every pipe invocation, dump all/some contents of the data into a log file, then the kind of monad you end up creating would be something like an "I/O monad".
- girishso 5y agoThat's a brilliant explanation of Monads.
- AzzieElbab 5y agoI did not mean to sound sarcastic, I am sorry it came out that way.
- danieltanfh95 5y agohttps://medium.com/glassblade/pragmatic-monad-understanding-c6f6447d1bcb https://medium.com/glassblade/pragmatic-monad-understanding-... Try this instead, simply put monads are used to provide an easier to use API to some black box abstraction. Example monads can include a "List" or a "Class" Why does Haskell etc need this? because its hard for them to make an easier to use API to access the internals of some abstraction due to the strict type system unless they use the monad pattern. In comparison in untyped FP everything is transparent while OOP allows you to create your own API within the abstraction itself. Funnily enough from this thread you can see all sorts of wrong ideas about Monads that beginner Haskellers have
- kayodelycaon 5y agoThanks! I can almost wrap my head around it now.
- wsc981 5y agoThis is actually a very understandable explanation, though maybe ‘thingy’ should be replaced with ‘mechanism’.
- deleted 5y ago[deleted]
- nowherebeen 5y agoThese context you list are higher order kinds.
- mdoms 5y agoDo you guys really look at a sentence like this and think, "yup, that clears it up"?