6 ms·
I didn’t know anything about monads before, now I’m curious what the point of one is
by BriggyDwiggs42 2y ago
I didn’t know anything about monads before, now I’m curious what the point of one is
- it_citizen 2y agoIt is a widely used analogy generator
- koolala 2y agoF
- MarkMarine 2y agoMaking burritos
- koolala 2y agoBurrito(Veggies)
- momentoftop 2y agoThere's no point as such. They are a natural (non-leaky) generalisation of a recurring pattern in mathematics and software over which you can build some general theory and, in the case of programming languages such as Haskell, a general purpose library. Haskell is one of the few languages that lets you write those general purpose libraries. In other languages, there's really no point talking about monads.
- VirusNewbie 2y agoScala supports it just fine.
- rvense 2y agoA "monad" is a description of something so general it covers lists, things that might not exist, things that might fail, and things that might happen in the future. It is a concept from category theory, which is the branch of mathematics that deals with saying as little as possible about as much as possible. You don't have to worry about any of this unless a teacher tells you to. (And if they do, you can just leave.)
- mmaniac 2y agoHaskell started using them because it allows a pure language to express side effects. Beyond that, they're a pretty general and reusable way of looking at data structures that nest.
- koolala 2y agoBurritos have side effects?
- Y_Y 2y agoMany impure functions take place in Taco Bell bathrooms
- juunpp 2y agoA "side effect" is generally the behaviour that can be modeled by a Monad under chaining (join), and is not necessarily IO (although IO is a Monad). For a burrito, the side effect of join is the union of burrito contents.
- int_19h 2y agoImagine eating a burrito bite by bite as you're performing a pure computation in your head. This would be captured as `Burrito Result` monad, where `Result` is the value that you're computing, and `Burrito` is the partially consumed burrito at the end of the computation. By representing it as a monad, you can pass said partially consumed burrito to someone else for them to compute while continuing to eat it, or you can delegate your computation to other people, passing burrito from one to the other. ~ So, yes, I suppose.
- chuckadams 2y agoA Human Centipede is a Monoid in the category of digestive tracts.
- koolala 2y agoDigital Spreadsheets lets you do this from multiple angles.
- chuckadams 2y agoMonads embody the concept of "chaining" functions. Every monad implements the chaining in a different way, but the user of the monad doesn't have to know how it's done. It's just "call this function on foo, take the result and pass it to the next" and so on. Plain old functions do it with plain old function composition (functions are monads!) but something like Maybe will return None if it gets a None, and only otherwise pass the data on. The Future monad will await completion then pass it on (async/await is a monad!), the List monad will merge together zero or more list results from mapping over each of its items, and so on. Again, the cool thing is that it's the same syntax no matter what kind of Monad you're in, so you can totally change the behavior of a monadic function by just using it with a more specific return type (at least in Haskell, other languages might make you pass around an implementation) Monads are a neat tool of composition, but composing monads themselves is fiddly and cumbersome, involving monad transformer "stacks" of deeply nested generic types. Monad transformers are really just not fun. I'd give specific examples, but I'm kind of lethargic from the burrito I had for lunch. If you're familiar with flatMap(), a Monad is anything that's "flatmappable" (which in JS is just arrays, but languages like Scala take it much further). In C#, it's IQueryable (LINQ is a monad!)
- aodonnell2536 2y agoWould it then follow that commands/builtins like `time` and `sudo` are monads? What about shell commands in general, since you can always chain together stdout to stdin with pipes?
- chuckadams 2y agoStreams are definitely monads, so if you're reading lines from stdin and printing zero or more lines for each to stdout, you basically have a List monad (Haskell's laziness makes every list a poor man's stream, though if you're doing serious streaming work, you'd probably want something more specialized). Mind you, shell pipes aren't actually implemented monadically, but you can certainly visualize it that way when working with functional libraries.
- jerf 2y ago"Monads embody the concept of "chaining" functions." No, it doesn't. Monad implementations may call the provided function zero times, or multiple times. Chaining implies exactly once, one of the common misconceptions about the monad interface. Flatmap is another common attractive nuisance; flatmap is the monad implementation for lists but is not "monad" in general, any more than "an iterator on linked lists" is "iterator" in general.
- kelseyfrog 2y agoIt's an abstraction - a very high level abstraction. Like all abstractions, if you squint hard enough, different things can look the same. Monads can make optionals, lists, error handling, i/o, continuations, state manipulation, reading values, writing values and many other things look the same.
- spion 2y agoThey are interesting in purely functional languages like Haskell because they allow for side effects without sacficicing purity and referential transparency. Rather than allowing side effects, you describe the program as, say, specs for the instruction to run, plus the function that decides what the next instruction is after the first instruction completes and yields a result. Kind of like a linked list of functions that return imperative instructions. I don't think the general concept is that interesting, at least in programming. Monoids, though simpler, are probably way more interesting (mapreduce, caching, etc)
- chuckadams 2y agoMonads are Monoids, so it's a good idea to build up an intuition for Monoids first. Then move up to Applicatives, and then finally Monads if you find you actually need them by then. By the time you get to them, Monads will be boring. Applicatives were dusty theory when I learned Monads, so they never burned themselves into my consciousness. I'm doing good with Monoids tho.
- lkitching 2y agoThe way in which monads are monoids isn't really helpful for understanding them for progamming.
- chuckadams 2y agoI dunno, it helped monads "click" for me at a theoretical level (they're just monoids in the category of endofunctors, what's the problem?) but by then I'd acquired a strong intuition of them already, so maybe it's not helpful for a novice. I'm pretty sure Applicatives help tho, LYAH seems to think so anyway. They sure would have helped me: the "Gentle Introduction to Haskell" was anything but.
- spion 2y agoMonads being monoids isn't very interesting in a practical sense - e.g. just because you can associatively combine steps in a program isn't very interesting. (We do it all the time when we extract a subset of instructions as a procedure) I'd say monoids are more interesting, mainly due to implications for massively parallel algorithms and caching and how finding operations that fit the laws let you reap massive benefits in both aspects. I've yet to see something as practically interesting for monads. Perhaps monadic parsers or STM qualify. What would you say makes monads just as interesting in a practical sense?
- program_whiz 2y agoThe easiest examples from mainstream languages are things like Result<T>, Future<T>, or Option<T>. Its honestly a very broad and vague way to say "some data with context". The advantage is that instead of using things like exceptions or panic/crash, your code must handle every case in order to get at the value unlike the normal case. For example, an Option<T> could force you to unwrap the value and deal with errors. In true functional languages and/or where pattern matching is used, you must handle both cases, presumably creating a chain of "monads" all the way down (as most of your functions will return Option<T> or Result<T, Err> type patterns, since you can't throw an exception, and any value might be empty/error, so you have to propagate it upwards). Honestly its a fancy term that functional programmers use to cow the laity. Its a bit like calling an if statement "probative procedural data query with indeterminate flow control."
- chuckadams 2y ago> Its a bit like calling an if statement "probative procedural data query with indeterminate flow control." Yeah, but "Monad" goes in the opposite direction, two syllables to sum up the whole deal. Also pretty typical for functional programmers :)
- lr4444lr 2y agoAssuming you're familiar with basic programming concepts, it is practically speaking just the abstract definition of a way to ingest and pass around data in an unfamiliar context. Promises are a great example (packaging data for async processing), or the "Optional" wrapper on JVM return signatures (Passing around an object for possible-null handlers). Both those implementations fail on some purity grounds, but they're good for understanding the gist of your question, i.e. "the point" of one. (Even though I'm 73% sure some Haskell-ite is going to respond to me with an _ACTUALLY..._)
- Tarean 2y agoLambdas have two hidden features: Variable capture lets you access variables/values from outer scopes, and statements/calling other functions lets you do control flow. Monads are types that let you build chains of lambdas, so you can mix control flow and variable scoping with the some type-specific logic. Async IO/streams/optionals are monads. It's no accident that these could be programmed as nested callbacks/nested loops/nested if statements. That's the nested chain of Monad->lambda->Monad->... Monads work well with syntax sugar (think async/await), and some languages like Haskell can abstract over them in neat ways.
- ww520 2y agoMonad provides a way to wrap types of data to process and chain them uniformly.
- bbminner 2y agoFor me, everything made sense when I read that generator functions in python can be used to implement algebraic effects, and algebraic effects and monads express the same ideas/logic using somewhat different language (and for some, including me, the algebraic effect lagngauge is easier). So I like an explanation that goes like "langaues without either but with exceptions and async io > generators/coroutines > algebraic effects > monads". On a fundamental level, all these describe abstraction over what happens "between functions calls" and how values are passed around. 1. Some languages provide special syntax for exceptions and async io - in both cases "something" might happen between function calls - either an exception handler is called under certain constitutions (eg prints logs) or a kernel level callback is created and the program is suspended. 2. One generalization of this can be implemented using python generator functions / coroutines - you can build a call graph by invoking all functions in you callstack as "yield from func()", and use "yield Exception" to propagate errors and "yield Timer(1)" to ask an outer caller (event loop) to wait, or "yield Print(mag)" if we want to keep our functions pure and make the C event loop handle all the IO. You can also pass values down the stack via corp.send(x). 3. But it is a little clunky. Some langaues like Koka give you an ability to define arbitrary "effects and effect handlers" which is essential special syntax for how we were abusing coroutines in the previous step that makes differentiating and handling different "kinds things that we pass up and down the callstack" (exceptions vs timers vs prints) easier. 4. But some langaues do not have effect handlers but still want to do "custom arbitary custom things between function calls". That's where monads come in - they define a type for defining chains/trees of function calls and rules for how these threes must be iterativley unwrapped and wrapped back depending on how the wrap looks like. Eg instead of doing a(b(c)) you say unit(c) | b | a and describe how piping must be done it terms of types of values that these steps process. I hope it makes it clear how one could implement side effect IO, or exceptions, or async io that pauses by defining how to "unwap such piping". In principle, you abstract away control flow by introducing your own syntax for building function call trees and then rules for writing piping that works with such trees. Monad guru please correct me if I am wrong.
- trealira 2y agoI think a good write-up that shows some practical use cases of monads is a paper called "Monads for functional programming" by Philip Wadler. It assumes you're familiar with the basic syntax of Haskell or its predecessors, though. https://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf https://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/b...
- lkuty 2y agoGood tutorial I think and I also appreciated reading the beginning of https://wiki.haskell.org/All_About_Monads https://wiki.haskell.org/All_About_Monads and watching "Don't fear the Monad" https://www.youtube.com/watch?v=ZhuHCtR3xq8 https://www.youtube.com/watch?v=ZhuHCtR3xq8