[HN Gopher] Monads are like burritos (2009)
       ___________________________________________________________________
        
       Monads are like burritos (2009)
        
       Author : ipnon
       Score  : 75 points
       Date   : 2024-06-02 12:25 UTC (10 hours ago)
        
 (HTM) web link (blog.plover.com)
 (TXT) w3m dump (blog.plover.com)
        
       | koolala wrote:
       | How many bites does a monad burrito take to eat?
       | 
       | 90.
       | 
       | https://archive.org/details/monadologyotherp00gott/page/217/
       | 
       | You don't even have to finish eating it to feel full.
        
       | tengbretson wrote:
       | And we all know that a burrito is just a lasagna in the category
       | of endofunctors.
        
         | koolala wrote:
         | praise math
        
         | mightybyte wrote:
         | Not endopasta?
        
         | layer8 wrote:
         | Is that like ravioli code?
        
       | BriggyDwiggs42 wrote:
       | I didn't know anything about monads before, now I'm curious what
       | the point of one is
        
         | MarkMarine wrote:
         | Making burritos
        
           | koolala wrote:
           | Burrito(Veggies)
        
         | it_citizen wrote:
         | It is a widely used analogy generator
        
           | koolala wrote:
           | F
        
         | momentoftop wrote:
         | There'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 wrote:
           | Scala supports it just fine.
        
         | rvense wrote:
         | A "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 wrote:
         | Haskell 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 wrote:
           | Burritos have side effects?
        
             | Y_Y wrote:
             | Many impure functions take place in Taco Bell bathrooms
        
             | juunpp wrote:
             | A "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.
        
         | chuckadams wrote:
         | Monads 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 wrote:
           | Would 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 wrote:
             | Streams 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 wrote:
           | "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 wrote:
         | It'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 wrote:
         | They 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 wrote:
           | Monads _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.
        
         | program_whiz wrote:
         | The 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."
        
         | lr4444lr wrote:
         | Assuming 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 wrote:
         | Lambdas 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 wrote:
         | Monad provides a way to wrap types of data to process and chain
         | them uniformly.
        
         | bbminner wrote:
         | For 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.
        
       | draw_down wrote:
       | I don't know how many times I've read things like this but it
       | doesn't seem to click. It's like a burrito with map and bind
       | functions? Well, alrighty!
        
         | vendiddy wrote:
         | Yeah seriously.
         | 
         | I feel like these kinds of concepts I to hear a few concrete
         | examples, then generalize.
         | 
         | These analogies usually don't click with me.
        
         | chuckadams wrote:
         | That's actually the point of the article. There used to be a
         | cottage industry in using real-world analogies to explain
         | Monads. I'm not sure whether it started as an in-joke or not,
         | but the most outlandish metaphor among others involved burritos
         | (other metaphors out there that really did exist: assembly
         | lines, toxic waste handling, and space suits). So now burritos
         | are an in-joke among Haskell programmers, sort of a whimsical
         | shibboleth.
         | 
         | Check my other post in this thread for what I hope is a more
         | accessible explanation of Monads. They're a very abstract
         | thing, so there's no concrete metaphors to be had, just a
         | common thread of piping values through "contextful" functions.
        
         | throwaway689236 wrote:
         | Yeah, seems like a lot of articles are written just to have a
         | catchy title.
        
       | tiagod wrote:
       | This was actually a great explanation. Still delivering 15 years
       | later. I wonder what other mathematical constructions are
       | abstractions of burritos.
        
         | Waterluvian wrote:
         | The application of the red sauce to the tortilla when the
         | burrito is resting on the plate describes a transverse Mercator
         | projection.
        
         | passion__desire wrote:
         | I have a general rule about abstraction. If the abstraction is
         | so general (e.g. a root node of a tree of abstractions), then
         | it's qualities will be reflected in every leaf node. Leaf nodes
         | such as snow, rock, water, trees or burrito.
        
       | ldjkfkdsjnv wrote:
       | Functional programming is dead. It never really caught on. For
       | all the articles I saw from 2010 - 2020, functional languages are
       | still as niche as ever. Influential languages like scala have
       | their best functional features pulled into java. LLMs will
       | further accelerate the decline. All the highest quality, most
       | crucial software I have seen is written in something like Java,
       | using classical OOP design patterns.
        
         | TwentyPosts wrote:
         | Counterpoint: Rust.
         | 
         | Seems to be taking off (difficult to predict the long-term, of
         | course), but Rust is excellent at functional paradigms and
         | Brings many advancements of functional languages to the people.
        
           | ldjkfkdsjnv wrote:
           | Rust is still extremely niche, large scale mission critical
           | software that runs big tech is not written in Rust
        
             | rcxdude wrote:
             | it's getting built into some pretty widepread applications:
             | firefox is a big one, it also runs a lot of the super-low-
             | level parts of dropbox. I'd say it's overtaken haskell for
             | adoption at least.
        
               | SoftTalker wrote:
               | Because it's really better, or because it's trendy?
        
               | chuckadams wrote:
               | It's more _practical_. I love me some Haskell, but you
               | 're never going to write Servo in it.
        
             | TwentyPosts wrote:
             | Linux Kernel, Firefox, Dropbox, Discord, Cloudflare,
             | Windows, AWS.
             | 
             | Idk, looking pretty good to me, unless you think none of
             | these count.
             | 
             | Considering everyone seems to hate C++ nowadays, and Rust
             | looks like the only existing alternative. Hard to imagine
             | the trend won't continue.
        
           | akira2501 wrote:
           | Rust? Why not just JavaScript? It's far more functional than
           | Rust and is much more widely used and deployed.
        
             | ovyerus wrote:
             | JS _is_ really good at FP, but it doesn 't have any real
             | concept of function purity and isolating side effects.
             | 
             | Rust has constant functions, for one: https://doc.rust-
             | lang.org/reference/const_eval.html
        
         | juunpp wrote:
         | "Most crucial software I have seen".
        
           | ldjkfkdsjnv wrote:
           | At big tech firms, there is no FP in the big crucial systems
        
         | Waterluvian wrote:
         | I've seen the complete opposite. So much total OOP nonsense in
         | Java.
         | 
         | You know what I think it means? That no single perspective will
         | ever be sufficiently complete to offer a meaningful opinion of
         | the whole.
        
         | koolala wrote:
         | FP? More like FF? "Fat and Flabby" jk its Free and Flappy like
         | Flappy Bird, flapping through a series of tubes
        
         | fifilura wrote:
         | > Influential languages like scala have their best functional
         | features pulled into java.
         | 
         | Here I feel you contradicted yourself, because the functional
         | patterns are making its way into mainstream languages.
         | 
         | Also, functional patterns has its special use in
         | distributed/parallel programming.
        
         | vendiddy wrote:
         | React is a functional pattern and is pretty popular.
        
           | akira2501 wrote:
           | Does it's popularity come from it's functional foundations or
           | just because a billion dollar corporation keeps it up to
           | date?
        
       | 12_throw_away wrote:
       | I often forget what a monad is, and need to keep reminding myself
       | "remember list.map and Option.and_then? if so, then you don't
       | _need_ to know what a monad is ". But will try thinking about
       | burritos next time to see if it helps.
       | 
       | I still don't get what they have to do with i/o in Haskell, but
       | am ok with i/o in Haskell being one of my life's forever
       | unknowable mysteries.
        
         | sunshowers wrote:
         | The way I think about it is that the general monadic structure
         | is that the results of an operation can cause new operations to
         | happen with equivalent complexity. This is exactly what "flat
         | map" is.
         | 
         | So what the "IO monad" in Haskell represents is the general
         | principle across programming languages where you can, say, read
         | a file, then for each line in the file read another file or
         | otherwise do additional I/O -- and this can spiral out in an
         | unbounded fashion.
         | 
         | As developers we can observe the monadic structure of
         | operations everywhere (and generally seek to avoid it! Monads
         | are fundamentally too powerful!) But whether it is worth
         | encoding the general idea of monadic structures into the type
         | system is a separate question. Haskell says yes, most others
         | say no. There are good reasons both ways. (One underappreciated
         | reason is that exposing a hierarchy of typeclasses/traits
         | introduces API stability considerations. When Applicative was
         | inserted in between Functor and Monad in Haskell, the whole
         | ecosystem had to be updated.)
        
         | roflc0ptic wrote:
         | (Tries to fight the urge to explain, fails) it's a construct to
         | sequence async interactions, one after the other, without
         | blocking. It's very similar to c# or python's await
        
           | minitech wrote:
           | I/O is just one thing that can be described with a monad.
           | `Option` with `and_then` as the parent suggested was another
           | example.
        
         | Cu3PO42 wrote:
         | I'd argue that if you know what Option.and_then does, you do
         | know what a monad is. and_then, known as flat_map or bind in
         | the generic case, is the quintessential operation of a monad.
         | 
         | One of my biggest gripes with Rust (and other languages) is
         | lack of a good monad abstraction (and accompanying syntactic
         | sugar). But I also acknowledge that this is a "I have done too
         | much category theory" problem and and_then is probably a more
         | reasonable name to those not familiar with this particular area
         | of maths.
         | 
         | > I still don't get what they have to do with i/o in Haskell,
         | but am ok with i/o in Haskell being one of my life's forever
         | unknowable mysteries.
         | 
         | They don't. Not really, anyway. IO happens to be a monad, but
         | that's not really relevant to it being used as an abstraction
         | around side effects. Haskell being a pure language is at odds
         | with the necessity of some side-effects, such as printing to
         | the console. The solution is to construct a "to-do list of
         | actions" or "blueprint" for desired side-effects. This is an
         | instance of IO. Any such blueprint that is assigned to the name
         | "main" is executed. That's it.
         | 
         | The monad part comes in when you want to construct this
         | blueprint. It so happens that one reasonable way to do this is
         | via flat_map.
        
         | lkuty wrote:
         | This might be interesting: https://jelv.is/blog/Haskell-Monads-
         | and-Purity/
        
       | gabesullice wrote:
       | I've referred to this blog post at least twice a year since I
       | read it 6 or 7 years ago. Not because I need to explain monads,
       | but because the "monad tutorial fallacy" [1] is an incredibly
       | useful concept to be aware of when trying to convey knowledge. I
       | encourage you to read about it :)
       | 
       | [1] https://byorgey.wordpress.com/2009/01/12/abstraction-
       | intuiti...
        
         | Symmetry wrote:
         | That reminds me of giving the advice, "Just do what comes
         | naturally," to beginners. That's the last advice someone who
         | has spent years building up an intuitive model needs, but it's
         | terrible for beginners.
         | 
         | https://putanumonit.com/2021/09/10/rules-for-noobs/
        
           | Swizec wrote:
           | Just do what comes naturally is _great_ advice for beginners.
           | See the pottery class parable:
           | https://www.industryweek.com/leadership/companies-
           | executives...
           | 
           | tldr: Pottery class, 2 groups. 1 group instructed to make the
           | perfect pot (graded by quality of 1 best pot). 1 group
           | instructed to make a bunch of pots (graded by pounds of clay
           | used).
           | 
           | At the end of semester, the group who was trying to make as
           | many pots as possible also produced the single best pot of
           | the class.
           | 
           | Lesson: You need reps. Lots of reps. You really do just gotta
           | do what comes naturally, get feedback, then do more. Doing is
           | the only way to learn tacit skills.
           | 
           | You can read about the best way to ride a bike for 10 years
           | and achieve nothing. Or you can spend an afternoon failing a
           | lot until you can ride a bike. Software architecture and code
           | structure are similar. You just gotta produce piles upon
           | piles of code and see what works.
        
         | mightybyte wrote:
         | Yes, this post is classic. My answer to Brent's "monad tutorial
         | fallacy" is https://mightybyte.github.io/monad-challenges/. It
         | was inspired by The Matasano Crypto Challenges that Thomas
         | Ptacek & others created awhile back which, instead of trying to
         | teach you cryptanalysis, guides you down the path of actually
         | doing realistic cryptanalysis with a series of challenges.
        
         | pdpi wrote:
         | For a long while now, I've been trying to write a monad
         | tutorial I'm actually happy to give people as an entry point,
         | and that point is precisely why I haven't put anything out
         | there yet. It's also the reason I keep trying: there's
         | something important to be learnt there in terms of
         | communicating tricky concepts.
        
           | kqr wrote:
           | I think the lesson is that tricky concepts have to be taught
           | by example.
           | 
           | Some theoretically-bent people can read a definition and
           | generate their own examples, but most people I've met need to
           | be presented with and taught one example at a time. After a
           | while, they just get it and the abstraction falls into place.
           | 
           | https://two-wrongs.com/the-what-are-monads-fallacy.html
        
             | pdpi wrote:
             | > I think the lesson is that tricky concepts have to be
             | taught by example.
             | 
             | The bigger insight, for me, is that they also have to be
             | taught by counter-example.
             | 
             | E.g. it's easy to find Functors that are neither
             | Applicatives nor Monads (usually, because you can't produce
             | a reasonable definition for `return`). It's surprisingly
             | hard to find a non-contrived example of a Functor that is
             | also an Applicative, but *is not* a Monad. Without that
             | counter-example, it's very tricky to build the intuition
             | for where the boundary lies.
        
               | andrepd wrote:
               | Now I'm curious: what's this non-contrived example?
        
             | chongli wrote:
             | _Some theoretically-bent people can read a definition and
             | generate their own examples_
             | 
             | This is what mathematical training taught me to do. It's
             | something I wish everyone could learn to do but high school
             | is too short to teach it to most people.
        
       | behnamoh wrote:
       | Monads are so easy. That's why there are 2,000 articles online
       | explaining how easy they are. :)
       | 
       | Okay hear me out:
       | 
       | I don't like exception handling, because it doesn't feel "pure"
       | and consistent with the rest of my program flow. If any errors
       | happen, I want to know what they are so I can plan ahead. You
       | might say "well, just catch your exceptions dammit". But see,
       | what if I forget to catch an exception right away and it
       | propagates? Also, other than Swift, I don't know of any
       | programming language that let's me explicitly mention if a
       | function could throw an exception. In Python, for example, you
       | can't just do Optional[str], because returning None is different
       | from raising an exception. So by just looking at a function type
       | signature, one can't know if it throws, which means you never
       | know if you should use try/catch or not.
       | 
       | But let's say you take care of all edge cases and return None in
       | those bad paths instead of raising exceptions. Let's also assume
       | that Python does't suck and it never raises exceptions by its own
       | standard libraries (e.g., json throws). The problem is: How do we
       | know if the function returned None because the evaluation was
       | None, or because it failed at some point?
       | 
       | So a better approach is to explicitly say the function returns
       | "something" which may or may not be there. If it's there, then
       | the function worked correctly, even if the value is None. If it's
       | not there, then the function failed. Go does this. Rust does this
       | better. Haskell has had this since ages thanks to Monads.
       | 
       | I like to think of monads as wrappers around data. In Python, I
       | simply write a Result monad (similar to Rust). In Haskell, this
       | is called a Maybe monad.
        
         | chuckadams wrote:
         | > I like to think of monads as wrappers around data
         | 
         | Technically they're a wrapper around a data _type_. Maybe Foo
         | is a Foo that might not be there, [Foo] is zero or more Foos,
         | etc. Which is actually describing a Functor, but Monads are
         | also Functors, the  "monadness" comes from the particular
         | functions like `bind` (or `flatMap`) that work on them.
        
         | airstrike wrote:
         | You might enjoy Hurl, the exceptional language:
         | https://news.ycombinator.com/item?id=40480056
        
           | behnamoh wrote:
           | I mean, I literally said I don't like exceptions :) But for
           | Hurl I'll make an exception!
        
         | flakes wrote:
         | > Also, other than Swift, I don't know of any programming
         | language that let's me explicitly mention if a function could
         | throw an exception.
         | 
         | Checked exceptions in Java. I both like and hate them.
         | 
         | They force the function to be explicit about what exceptions
         | they can raise. If you call a function that raises a checked
         | exception, you must either explicitly handle the exception, or
         | mark that it is propagated up by adding the same exception to
         | the calling method signature.
         | 
         | However, they cause a lot of pain for working with higher order
         | methods (map, filter, flatmap, etc). Because they change the
         | signature of the method (and therefore the interface it can
         | satisfy), you need to use a lot of generic variants of higher
         | order methods to accept them, or like a lot of libraries, you
         | end up writing wrapper functions that convert the checked
         | exceptions into unchecked runtime exceptions, such that they
         | don't modify the method signatures. This then leads to a lot of
         | weird code, and uncaught exceptions at runtime, taking down the
         | application.
        
       | justinpombrio wrote:
       | Jerf wrote a great monad tutorial for people who have read too
       | many monad tutorials (like this one):
       | 
       | https://www.jerf.org/iri/post/2958/
        
         | scythmic_waves wrote:
         | Thank you! I was trying to find this the other day but
         | couldn't.
        
       | SatvikBeri wrote:
       | My favorite approach is from Functional Programming in Scala,
       | which doesn't mention monads until chapter 11. But it has you
       | implement a bunch of collections with `map`, `map2`, `unit`, and
       | `flatMap`, and exercises that repeatedly show how useful this
       | interface is. So by the time you get to it, the definition of
       | Monad feels obvious, as well as Functors & Applicatives.
        
       | brudgers wrote:
       | Not really related, https://the21stcenturymonads.net/
        
       | Mathnerd314 wrote:
       | > But he said no, I was the lone genius.
       | 
       | I think that's the issue? Haskell was designed by and for
       | geniuses (Larry Wall). But Python... certainly Guido likes
       | compliments but for the most part he was an average programmer,
       | designing for other average programmers. And now Python is #1
       | while Haskell is only #28. Like if you just skipped the "monad"
       | terminology and called them "promises" or "futures" everybody
       | would be less confused.
        
       | avodonosov wrote:
       | Explanations with bad analogies are really a very often problem.
       | 
       | Although this author matched monads with burritos relatively
       | well. Except for the purpose - we know the purpose of burritos,
       | but this does not help to understand the purpose of monads (for
       | programming, in particular).
       | 
       | But sometimes a concept is named after a bad analogy by the
       | concept authors (and probably even invented after that bad
       | analogy, although maybe the authors just use poor name because
       | they fail to clearly recognise the essence of their solution).
       | Like mixins. I satirise that in my Mixin FAQ
       | 
       | Q: What is a mixin?
       | 
       | A: Mixin allows to inject functionality into classes. Mixins
       | first appeared in the Flavors system and were inspired by an ice
       | cream shop offering a basic flavor of ice cream (vanilla,
       | chocolate, etc.) with a choice of optional "mix-in" ingredients
       | like nuts, cookies, candies, etc.
       | 
       | Q: Can I mix-in a ServerSocket into a ColorPicker?
       | 
       | A: Yes, why not.
       | 
       | Q: How will it work?
       | 
       | A: Like ice cream with cookies.
        
       | frabjoused wrote:
       | Is something that is so inherently hard to explain while giving
       | it justice truly practical or even worth it? If you are in a room
       | with 10 devs, how many will have a deep understanding of monads?
       | And if it is expected to be only a few, is it really constructive
       | to have it in the codebase? Or is it just going to trip people up
       | and be misapplied.
        
         | williamcotton wrote:
         | If your codebase is written in F#, OCaml or Haskell then it
         | would be surprising if there were no use of monads as it is a
         | pretty common design pattern in a functional language.
        
         | bawolff wrote:
         | I think the real question is more - is the language of category
         | theory really worth it here.
         | 
         | Monads as a concept is basically just a fancy version of a
         | wrapper class (if you in OOP land). Do we really need the
         | cognitive overhead of advanced mathematics to explain that?
        
           | agentultra wrote:
           | You can get by on intuition but you won't get far.
           | 
           | If you want to limit yourself and make sure people keep
           | reinventing the same concepts over and over, sure, avoid
           | maths.
        
         | djur wrote:
         | You don't need to have a deep understanding of monads to use
         | them. Plenty of languages are built on concepts that their
         | users aren't expected to understand thoroughly.
        
       | massysett wrote:
       | Monads are easy.
       | 
       | What's hard is higher-order functions, parametric polymorphism,
       | and ad-hoc polymorphism via typeclasses. Understanding any one of
       | these is hard. Understanding all three is harder. Understanding
       | all three applied simultaneously is harder still. That's what
       | monads are.
       | 
       | On top of all that, understanding "monads" doesn't mean too much.
       | IO does something, Maybe does something else, StateT something
       | else.
       | 
       | But once you understand all that, monads are easy. Maybe monad
       | analogies helped somebody understand all that, but they didn't
       | help me.
        
       | williamcotton wrote:
       | A Burrito Is a Monad (2024):
       | 
       | https://www.williamcotton.com/articles/a-burrito-is-a-monad
       | let burrito =          tortilla         >>= addMeat Chicken
       | >>= addMissionBurritoIngredients         >>= holdThe Cheese
       | >>= addIngredient PicoDeGallo         >>= addIngredient Salsa
       | >>= addIngredient Guacamole         >>= addIngredient SourCream
        
       | davesque wrote:
       | I always felt like the one thing I wanted in a monad tutorial was
       | a list of things that _aren 't_ monads because they follow all
       | the monad rules except for one, for each rule.
        
       ___________________________________________________________________
       (page generated 2024-06-02 23:01 UTC)