4 ms·
> now you know what a monad is... therefore you will be unable to explain to anyone what a monad is Isn't a monad effectively just an abstract wrapper for some
by supermatt 3y ago
> now you know what a monad is... therefore you will be unable to explain to anyone what a monad is
Isn't a monad effectively just an abstract wrapper for some properties that you can apply sequential transforms on? Why do people keep making out they are some form of voodoo?
- lgas 3y agoNo, they are not wrappers. I know what they are though, so I won't be able to explain them to you.
- noelwelsh 3y agoThat's definitely a sufficient understanding to make progress with. It doesn't describe every monad but it describes the ones you will commonly meet when programming, and it provides enough understanding to scaffold further understanding of the more abstract concept. A lot of the "it's so hard" BS is from people who think you have to understand a concept in its full generality in one shot. That's definitely not how effective learning works in most cases.
- bowsamic 3y agoBecause, that's nowhere near general enough to describe what monads can do, that is, your explanation is wrong because of its over-specificity. That's the problem with monads. They are an extremely general mathematical object, but the specific uses of them are wildly different. It's the exact same "problem" with functor and applicative. It's like explaining a vector space using the analogy of arrows in space and then having to explain how sets of functions are also a vector space. In mathematics you just have to stick with the general definition and a few examples, keeping in mind that those examples are specific. Most programmers are simply not used to thinking in that way. That's why it's "some form of voodoo". Further, much like the definition of a vector space does not make it immediately obvious that functions can be vectors, it's not obvious from looking at the definition of a monad that it allows us to do sequential IO. That's why people think it's some sort of voodoo. You have to just accept that the example obeys the definition, the example doesn't fall out of the definition.
- supermatt 3y ago> Because, that's nowhere near general enough to describe what monads can do Totally disagree. You are effectively saying you cant define anything unless you include every case, which is clearly nonsense. > it's not obvious from looking at the definition of a monad that it allows us to do sequential IO The transform is "transform the wrapped properties into some IO call", and all transforms are explicitly sequential.
- bowsamic 3y ago> You are effectively saying you cant define anything unless you include every case, which is clearly nonsense. No I'm not. I will repeat what I said again: such things are defined by their general mathematical definition, and any analogy can only speak for certain subsets of examples of that definition. > The transform is "transform the wrapped properties into some IO call", and all transforms are explicitly sequential. How exactly does the mathematical definition of a monad say anything about "transforms"? I think you didn't actually read my comment.
- supermatt 3y ago> How exactly does the mathematical definition of a monad say anything about "transforms"? Im not sure that it does, but a "transform" as I mean it in my basic description is applying an operation to the "wrapped" properties.
- bowsamic 3y agoThe transformation mentioned there has nothing to do with using the bind operator within a monad. An example of a natural transformation would be transforming from one monad to another monad
- uxp8u61q 3y agoThe word "transformation" in that name has absolutely nothing to do with your use of the word "transform" ("transform the wrapped properties into some IO call"). MacLane could have decide to call natural transformations "widgets". My point is, besides the name (which is completely arbitrary), why would you even begin to believe this has something to do with "transforming properties into IO calls"? Nice shadow edit. For context, the previous comment used to consist of a single link to https://en.wikipedia.org/wiki/Natural_transformation https://en.wikipedia.org/wiki/Natural_transformation
- rebeccaskinner 3y agoFor people learning Haskell, one of the big challenges I see is that learning about monads is often when people need to start understanding higher kinded types. It’s not so bad as long as you focus on container-ish things like lists, Maybe, and Either, because people tend to have an easier time thinking “the m is the box and the a is the value inside it”, but it really tends to throw people off balance when they need to think about something like IO or State where the intuition is less immediately obvious. Ultimately I don’t think learning them has to be hard, but it can be, and it does usually require a bit of patience to let the full picture sink in.
- platz 3y agoDefinitely agree about intuitions, I think even experienced people can have issues when a type has a lot of type variables. What do they all mean? It's almost like an implicit API you need to learn for that particilular type, with varying levelsnof documentation or lack thereof
- Exuma 3y agoCan you give an example of the full picture to someone who doesnt know haskell? The only functional language I'm familiar with is elixir. I tried learning about them for fun but couldn't see many examples unless I know all of the weird haskell syntax. The core basis that I gathered of functors is that they're like anything which is "mappable", the key part being it can be any type, and not something like a list or array. So maybe you have an object data type, and you create a custom function which makes it mappable. The basis of monads was a functor that returns another functor, and the example I saw was a "stream". Elixir does have streams, and this "makes sense" but I wasn't super satisfied with that answer as I highly doubt all this talk of making it hard to understand is about streams. Is there an actual example that exists where you can present the different ways to solve it? Ie... you have X data structure, and you want to get Y parts out of it while transforming Z at the same time. Method 1: no monads, Method 2: monads, or something like that?
- assbuttbuttass 3y agoOne example would be to simulate some form of early return from a procedural language. Suppose you have a function which executes some operations, and these operations can sometimes fail, so they return a Maybe (probably Elixer has some form of optional type) You could write this without making use of Monads using: f = case op1 of Nothing -> Nothing Just x -> case op2 x of Nothing -> Nothing Just y -> case op3 y of ... Or you can use the Maybe monad to make this a bit nicer f = op1 >>= (\x -> op2 x >>= (\y -> op3 y >>= (\z -> ...))) Or you would probably use the do notation, which is just shorthand for >>= f = do x <- op1 y <- op2 x z <- op3 y ...
- the_af 3y ago> Isn't a monad effectively just a [something]? I think this article responds well to that kind of "it's so obvious!" flash of insight: "The Monad Tutorial Fallacy", https://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/ https://byorgey.wordpress.com/2009/01/12/abstraction-intuiti... Basically, you have to build your own intuition. Examples of monads are just examples, what matters is how you reached that insight, and there's no shortcut for that; you cannot simply be told that "monads are like wrappers" (or burritos, read below). Like the article states: > “Monads are easy,” Joe writes. “Think of them as burritos.” Joe hides all the actual details about types and such because those are scary, and people will learn better if they can avoid all that difficult and confusing stuff. Of course, exactly the opposite is true, and all Joe has done is make it harder for people to learn about monads, because now they have to spend a week thinking that monads are burritos and getting utterly confused [...] > What I term the “monad tutorial fallacy,” then, consists in failing to recognize the critical role that struggling through fundamental details plays in the building of intuition. This, I suspect, is also one of the things that separates good teachers from poor ones. If you ever find yourself frustrated and astounded that someone else does not grasp a concept as easily and intuitively as you do, even after you clearly explain your intuition to them (“look, it’s really quite simple,” you say…) then you are suffering from the monad tutorial fallacy.
- bvaldivielso 3y agoI don't know that this definition is very precise. For example, the kind `(->) r` (which you can roughly understand as the class of all functions that go from a fixed type `r` to other types) is a monad in haskell [1]. In what sense is this class of functions a "wrapper"? Additionally, even if you insist that this reader monad is a "wrapper", your definition would also informally apply to things like `Applicative`, and not all applicatives are monads (some are). Some monads are more easily understood as wrappers (`Maybe`, `List`, ...) and you can be very productive if you just stick to that level of understanding. But there's a deeper understanding that one can get. [1] https://hackage.haskell.org/package/mtl-2.3.1/docs/src/Control.Monad.Reader.Class.html#MonadReader https://hackage.haskell.org/package/mtl-2.3.1/docs/src/Contr...
- ImprobableTruth 3y agoTake the state monad : state -> (a, state). I think one would only count that as a wrapper by squinting really, really hard.
- Tainnor 3y agoI think of monads mostly as "an implicit context on which we can perform operations in sequence", which is maybe similar. But I'll agree with other people here that you really have to build up your own intuition by working through examples and maybe trying to write your own Monad instances, etc. Otherwise you will apply this intuition in a subtly wrong way. There are so many cool monads that work differently from IO, Maybe and such types, e.g. the binary package allows me to write data Header = Header Word8 Word16 parseHeader :: Get Header parseHeader = Header <$> getWord8 <*> getWord16le or for a more complicated example data Header = Header [Word16] parseHeader :: Get Header parseHeader = do size <- fromIntegral <$> getWord8 fields <- replicateM size getWord16le return $ Header fields and then I can later run parseHeader on some binary input to parse a header, and I can do it in one go or I can run it incrementally, it really doesn't matter, because the Get monad only describes the way the input should be parsed and not the actual parsing algorithm.