14 ms·
The simplest explanation of Monads I've ever read (as a Python developer) was actually one in a comment by a Hacker News user 'frio': http://news.ycombinator.c
by lhnz 14y ago
The simplest explanation of Monads I've ever read (as a Python developer) was actually one in a comment by a Hacker News user 'frio':
http://news.ycombinator.com/item?id=4960701 http://news.ycombinator.com/item?id=4960701
- runT1ME 14y agoThat is an incorrect explanation fyi...
- lhnz 14y agoDammit, how wrong?
- lobster_johnson 14y agoThat's a decent explanation that covers part of what monads are, although since it uses Python, it cannot express the type goodness that comes with monads in languages such as Haskell and, more recently, Rust. Both Haskell and Rust exploit compile-time typing to avoid having null (or nil, or None, or whatever) pointers in the language -- something which eliminates an entire class of errors that plague most of today's languages, including Python. The reason they can do this is that with Maybe, the wrapped value is either something (Just a) or nothing (Nothing). Since Nothing is a type (more technically a type constructor), not a value -- unlike something like Python's None, or C++'s null -- it cannot be passed as the value to a function which expects a valid pointer to a different type: -- This won't work setUserName(user, Nothing) Another thing about Haskell is that the IO system relies on monads for a very specific reason, or maybe two reasons. Since Haskell is lazy and pure, it needs a mechanism to express the fact that a function has actually done some work, even though -- from the compiler's point of view -- it hasn't. For example, consider a function call such as: putStrLn "Hello world" Well, this function has nothing particular to return; in most languages it would be a "void" function or return a null value. But this would not work in Haskell, which is designed to (1) optimizes function calls that return the same value (so if you call this more than once, Haskell would normally just evaluate it once), and (2) completely eliminate function calls whose values are not used. For this reason, Haskell's putStrLn has to return a unique value every time it's run, just to convince the compiler that it should not be optimized away. And so it does -- this is the IO monad. putStrLn returns a new IO value for every call. Since it always returns a new value, this ensures that Haskell won't optimize it away. There is another aspect to the IO monad: Haskell being lazy and pure, it's allowed to evaluate everything out of order. The way the IO monad is passed, baton-style, between each operation ensures that the compiler is forced to evaluate I/O operations in the sequence they appear in the code. Well, mostly. You still have to be careful; you can easily end up in a situation where a read is only evaluated after you closed a file, for example. (I'm not a Haskell expert, so I would be happy to be corrected on any point. Note I have glossed over some technical details in my explanation that would just complicate things.)