Inventing Monads

  • > This begins to get us to the fundamental abstraction of a monad: a box, with an interface for map, and flatMap

    Before I understood monads, I read variations of the above sentence a million times, always got stuck here: https://i.imgur.com/McThkuh.png

    How does this abstraction let us perform IO, do in-place destructive updates, etc? The answer is that it doesn't. These must be primitives supplied by the runtime. A monad like IO has its two functions (return+bind), and a bunch of other magic functions. It's obvious now but that fact is hardly ever stated.

    I wonder if anyone has tried explaining from the other direction? Rather than building up to Maybe, try building down from a desire to print Hello World.

  • In various places on the web one can find the quote that 'Dependency injection is a 25-dollar term for a 5-cent concept'.

    I feel it is the same with monads including all the false suggestions that one might need to understand category theory and similar such nonsense.

  • There's also the classic http://blog.sigfpe.com/2006/08/you-could-have-invented-monad...

    Written by a 3-time Oscar winner, no less!

  • To understand monads, I think it helps to know a language where expressing such a concept is more natural. Although I do not claim to know 100% what monads are yet, coming across these features made it easier for me to understand the concept a little bit.

    - Algebraic data types

    - OCaml's let expressions

    - F#'s computation expressions

    I also think that it is important to write something that naturally requires the use of monads. One thing that spring to mind is Parser Combinators.

    - https://fsharpforfunandprofit.com/posts/understanding-parser...

    - https://www.youtube.com/watch?v=N9RUqGYuGfw

  • I really like how this article builds up from a simple real life use case.

    Shameless plug for my own article that did something similar about a week ago: https://medium.com/@ameltzer91/an-easy-to-understand-monad-g...

  • I think the hard part for most people is moving beyond Maybe/Either. It’s hard to find motivating examples when most languages lack denotational semantics and everything implicitly happens inside IO all the time.

  • As someone who isn't familiar with functional programming, what benefit does this give us over throwing an error when trying to access a resource that doesn't exist?

  • That code that "is getting pretty ugly" seemed ok to me.

  • I had a similar example today in the functional programming slack.

    > hello, quick question: i feel like there's a more elegant way to express this, but I'm struggling to come up with one:

        foo :: (a -> Bool) -> (a -> Bool) -> a -> Bool
        foo f g x = f x && g x
    
    For those who aren't as familiar with Haskell, that is taking a function f and a function g, passing argument x to both, and then doing a binary and on their boolean result.

    One answer suggested:

    > You can get fancy, but the “simple” version is almost always more readable:

        (not . null . f $ x) && (not . null . g $ x)
    
    Which I find myself agreeing with in many ways, but for some reason leaves me desiring more.

    The answer to that desire complements this article I think:

    > if f and g returned Maybe you could have:

        > f _ = Nothing
        > g _ = Just ()
        > x = ()
        >  (f x) <*> (g x)
        Nothing
        > import Data.Maybe
        >  (f x) <*> (g x) & isJust
        False
        > -- or to avoid <*> you can do
        > liftA f g x
        Nothing
    
    If that's not clear, let me know what's confusing and I'll try to explain further

  • How many Monad explanations need to be written before we admit that the Monad is an unsatisfactory abstraction for practical purposes?

  • I wrote an article with the same name! [1] The problem solving based approach seems to be the most relatable and easy for people to get an idea of what monads are. Nice work.

    [1] https://blog.kabir.sh/inventing-monads

  • I think, the main benefit of FP is alsoits main problem.

    Patterns like the monad are so abstract, that ob its own nobody knows what to do with it, but it makes them so very powerful.

    OOP patterns, on the other hand, come from a more inductive source. They are more concrete, but also not as powerful. Easier to grasp, but less concise.

    We need a step (or more) between the definition of FP concepts and their application, to make all this more approachable for the average programmer.

  • undefined

  • I thought I understand monad after reading the article, but then I read the comment and now I am confused what is monad (again)?

  • I wonder why it isn't ever described as a design pattern? For me, it is one..

  • [Edited away]

  • So do you need monads in Haskell because that's the only way you could do some of the things that are trivial in an imperative language (albeit verbose and arguably inelegant)?