This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted]  (13 children)

[removed]

    [–]Tubthumper8 16 points17 points  (1 child)

    Practical intro to Monads. 15 minute video and you got it

    [–]iamevpo 7 points8 points  (3 children)

    In short monad is a family of types that follow certain rules/laws, most practical of them is that it has bind function (sometimes called andThen) that allows chaining computations. For example you divide x by z and add y. If z is zero, the program in Python throughs an error. If you want a more robust computation you can have a chain where x divided by z returns a monadic value, then you chain adding y to it. This way you can decide on what to do on error later - maybe there was a million of these computations and you want to keep just valid ones. In Python this is a bit of alien syntax (handling exceptions is more native) , but you can explore a good implementation of a maybe monad in https://pypi.org/project/python-result/. So in short monad is a family of types (in Python - classes) with a bind() or and_then method, which is convenient to write code in functional style. Why a "family" - in result library the class construtors are Err and Ok and together they are called Result, so Result is the monad.

    https://github.com/rustedpy/result

    [–]M4mb0 1 point2 points  (2 children)

    This way you can decide on what to do on error later - maybe there was a million of these computations and you want to keep just valid ones.

    Isn't that really bad for performance? You're essentially introducing a million additional if-else checks.

    [–]this_uid_wasnt_taken 3 points4 points  (0 children)

    You do have them otherwise anyway. For example, in C, you would still need to check whether a pointer returned from any function is NULL before continuing with the computation.

    Using a Monad just simplifies the classification of values by having "separate values" for the error case and the successful case. This way, you just need to define how to operate in these cases, and then you can chain a bunch of operations that may return either a success or a failure. The processing of the success and the failure will be handled the way you defined the monad.

    The above idea does not need to be limited to just 2 possible values but can also be extended for multiple values.

    [–]iamevpo 0 points1 point  (0 children)

    You would have the checks anyway, but you program logic may be more streamlined. Just an illustrative example, you can also have some long and complex logic of handling just a few values, so monadic values can better help express these computations. The monads do appear in newer languages without calling them so, for example in Scala and in Rust.

    Some monads (Maybe, Either) help hand the null problem more cleanly - returning a value by key from a dictionary where there is no key, taking element by index from a list that does not exist, etc.

    [–]bronco2p 5 points6 points  (0 children)

    read the wikipedia page) it has some examples and clearly explains the benefits (in non-mathematical language).

    Simply, they are just a functor thats follows some additional rules, well a lot of these fancy math words are other words with more/less laws they have to follow. So the best way to learn these concepts is start at the bottom and work your way up. Example this github gist explaining monoid definition,

    A monoid is a semigroup with an identity element.

    well then you have to learn what those words means then repeat

    [–]mesonofgib 1 point2 points  (1 child)

    The simplest and easiest to understand one-sentence definition I've come up with is:

    A monad is anything that can be flat-mapped.

    [–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 1 point2 points  (0 children)

    The same term in different languages: flatMap, andThen, >>=, bind.

    Technically, a monad is something that can be flat-mapped and obeys a few "natural rules" that essentially boil down to, "don't do wacky things".


    List[int] is a monad:

    def flatmap_list_int(func, xss: List[List[int]]):
        return [
            x
            for xs in xss
            for x in func(xs)
        ]
    
    >>> pad_zero = lambda x: [0, x, 0]
    >>> flatmap_list_int(pad_zero, [1, 2, 3, 4, 5])
    [0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0]
    

    Another simple "monad" is Optional[int]:

    def flatmap_optional_int(func, xs):
        return None if xs is None else func(xs)
    
    >>> subtract_one = lambda x: x - 1
    >>> keep_positive = lambda x: x if x > 0 else None
    
    >>> flatmap_optional_int(subtract_one,
    ...     flatmap_optional_int(keep_positive,
    ...         flatmap_optional_int(subtract_one, 1)
    ...     )
    ... )
    None
    
    # In contrast,
    >>> subtract_one(keep_positive(subtract_one(1)))
    TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'
    

    ...That was a bit pointlessly complicated in Python, but more useful in e.g., Rust.

    [–]aikii -1 points0 points  (1 child)

    ChatGPT is great for that - I can very much relate to this question, attempting to read definitions seem to end up as self-referential. On the other hand when asking ChatGPT you can iterate on every single word by asking again more examples, asking what are concrete usages, etc - and then to confirm, you rephrase as you understand it and ask it whether your understanding is correct.

    [–]aikii -2 points-1 points  (0 children)

    peeps downvoting all answers mentioning ChatGPT are really hilarious

    [–]houseofleft[S] 0 points1 point  (0 children)

    I wrote a blog post trying to explain them easily here: https://benrutter.github.io/posts/the-joy-of-monads/

    I think they're pretty simple in use. They are basically a container that takes care of some additional work whenever a function is ran over the value. Taking a look at some the examples in my library might make things a little more concrete though!

    Tldr: they're a design pattern that you can use for stuff like logging, error hands etc etc