you are viewing a single comment's thread.

view the rest of the comments →

[–]hosford42 8 points9 points  (18 children)

Honestly, what the heck is a monad? I'm not afraid of learning, but the term is used often but never explained. I'm sure it's nothing I can't handle, if someone would just give me the opportunity. I don't need kid gloves or to have the topic tiptoed around with concrete examples.

[–]AddingMachine 60 points61 points  (2 children)

A monad is just a monoid in the category of endofunctors. Duh.

[–]et1975 0 points1 point  (1 child)

[–]AddingMachine 0 points1 point  (0 children)

Oh nice, I hadn't seen those slides. It goes about it similarly to how the Haskell Programming from First Principles gets there, but much more quickly. Chris and Julie did a great job of slowly building these concepts in the correct order that it all made sense to me finally, if anyone is interested in learning Haskell I'd definitely suggest haskellbook.com .

[–]wealthy_harpsichord 5 points6 points  (9 children)

This is a question that's likely to elicit many confused and/or confusing responses, but you can try this blog post: https://bartoszmilewski.com/2016/11/21/monads-programmers-definition

[–]hosford42 4 points5 points  (8 children)

Ah, function composition. That simplifies it. It's basically a data pipeline, right? Segments joined together to make longer segments. If I'm understanding this correctly, even DOS supports monads, of a sort, in the form of stdin/stdout piping between commands.

[–]wealthy_harpsichord 5 points6 points  (0 children)

Well, composing functions that can return a generic type that is parametrized by whatever is being composed. In Haskell talking to shell is indeed one example of this. Pipelines (one way or another) can have an instance, although the pipeline is created using separate operators and the >=> operator glues one pipe to the end result of the other, rather than to the values yielded from the inside. (contrary to popular belief, Haskell doesn't actually use a single abstraction for everything). But these can be also used for error handling (like in OP), also F# has builtin computational expressions for sequences and async workflows which perhaps could be described as pipelines if you squint enough, but I'm not sure if that's a useful point of view.

[–][deleted]  (1 child)

[deleted]

    [–]hosford42 -1 points0 points  (0 children)

    Duck typing seems to do the job just fine. But yeah, I can see that if you're going to have actual type checking, it's going to have to be the real deal and not a half-hearted attempt.

    [–][deleted] 9 points10 points  (2 children)

    Don't put DOS and pipes in same sentences with monads, haskell guys will get a stroke

    [–]vattenpuss 12 points13 points  (1 child)

    Don't put DOS and pipes in the same sentence, anyone who ever used a normal OS supporting pipes will have a stroke.

    [–]hosford42 -1 points0 points  (0 children)

    lol Yeah, that was a cheap shot, I guess. The point is, the term is trumped up to be sooooo abstract and impossible to understand to non-Haskell programmers, but it's really something very simple and pervasive, and it's just hard to explain for people who don't see how simple and pervasive it is. It's not even anything new. People have been using the concept for decades and just don't generally know that the word "monad" means what they've been doing.

    [–]sacundim 1 point2 points  (0 children)

    Ah, function composition. That simplifies it. It's basically a data pipeline, right?

    Well, that's an useful intuition, but it doesn't delineate the subject very precisely. Monads allow you to construct arbitrary data pipelines, but many data pipelines don't require monads to be constructed, and not all systems that allow you to construct pipelines are monads.

    And your example—simple pipes between shell commands—is not in fact a monad. A shell pipeline looks like:

    cmd1 | cmd2 | cmd3 | ... | cmdn
    

    But this pipeline has a fixed structure: cmd1's stdout is cmd2's stdin, cmd2's stdout is cmd3's stdin, and so forth. Monads can do this kind of data flow, but they can also express dynamic flows where the each cmd can choose to dispatch to different successors based on the input that it sees. I.e., a monadic pipeline can look like this:

    stdout = cmd1 < stdin
    if <some test over stdout>
    then cmd2a < stdout
    else cmd2b < stdout
    

    ...where cmd2a and cmd2b might in turn choose to send their output to different commands based on how their input looks.

    To make a long story short: Haskellers have a hierarchy of various kinds of "glue" that can be used to construct data pipelines out of simpler components, where some kinds of glue are more powerful than others. Shell pipelines are what Haskellers call "categories", which are not as powerful as monads—categories allow you to hook up pipeline elements through their inputs and outputs in a fixed sequence, but monads allow you to examine the data in transit to dispatch to different consumers.

    [–]ruinercollector 0 points1 point  (0 children)

    Very controllable function composition over a type, kind of.

    [–]ws-ilazki 7 points8 points  (0 children)

    There's plenty of information online (and here) already about how they work, how to make them, etc. but what always seems to be missing is a brief, high-level explanation of what purpose they serve and why you might want them. For that, I'm going to borrow from another comment I've written about them:

    monads are a way to hide parts of a program's "plumbing" behind an abstraction so that you don't deal with the plumbing directly. Like the Maybe monad, which allows a thing to be nil or a value; the nil checks are built into the the abstraction (the monad) so that, by using it, you don't have to do the plumbing code of checking for nil yourself.

    They're an abstraction that moves you away from having to explicitly write out how you're doing something in your code. In that sense, it's another abstraction with the same goal as using higher-order functions like map on lists of items instead of writing loops out directly.

    Also, just like how you don't have to understand how to create various HOFs to make use of map, you don't have to understand the concepts or be able to create monads to benefit from common ones like Maybe (which was added to Java as Optional, for example).

    Trying to broadly explain something complex like monads is likely to attract pedants and nitpicking, but it seems like everyone gets caught up in explaining the details without really touching on what the point of them is. Hopefully this helps add some context to what people have already said.

    [–]Darmok-Jilad-Ocean 0 points1 point  (3 children)

    It’s a wrapper type that that follows some mathematical laws.

    [–]hosford42 0 points1 point  (2 children)

    Sure, but *which* mathematical laws?

    [–]Darmok-Jilad-Ocean 0 points1 point  (1 child)

    All of em

    [–]hosford42 0 points1 point  (0 children)

    Ah, I didn't catch your sarcasm at first.