shapr explained monads on #emacs 2003-02-23. The first explanation I really understood.
A monad is something that is defined by two ’methods’ and three laws, and allows purely functional code to safely handle side-effects. It’s how Haskell can remain purely functional, and yet do side effects.
You know you can explicitly pass state, right? A state monad hides the explicit state passing in its subclass of function call. Think of a calculator. You always have a result on the display, right? When you start up the calculator, it says 0. When you start up a monadic calculator, you pass in the 0 as the initial state. So, if you do add 1 on the calculator, there are three inputs, the state that’s on the display, the operator, and what you just typed: Two explicit inputs, and one implicit. The state monad passes around the implicit input for you, you don’t have to explicitly write code for it.
The calculator is like an automaton, but a monad is much more general than an automaton. This is just one thing monads can do. Monads a safe way to subclass function call for a certain group of things.
Another example is the Maybe monad... This is based on “What the hell are Monads?” by Noel Winstanley (1999).
Think of a database where you have
if (select user from user_table): if (user has enough money): if(have item in stock): send package to user.
You’ve probably run across one of those places where you have a massive if/else tree and you think “There must be a better way” The Maybe monad uses some cool tricks to subclass the function call that happens between these pieces of code so that if one of the fails, none of the rest of them get called.
So you could do:
user <- select user from table send item user <- select count(item) > 0
So you see that subclassing function call saves lots of work when it comes to automatic failure handling, yah?
There are lots of monads, there are even monad transformers that let you create multi-flavor monads that combine any monad features that already exist.
Q. Don’t monads complicate the code?
A. Not really. You define the explicit passing **once** in the monad then ← calls whatever you defined for that monad.
Related:
I don’t like object oriented programming. Object orientation is a nice way to think about your code, if you are solving problems that involve real objects. But to code a search strategy as an object? Furthermore, if you keep all the code together with the data, doesn’t that make it more difficult to understand how objects interact? You have to open dozens of files in order to get the picture. Then you start modelling interactions as objects, because then you get to keep the code in one place again. And you use specific class browsers to make switching files easier. But all this illustrates is that object orientation only makes sense for a very limited set of problems:
Thus, object orientation makes sense when you simulate telephone switching networks (this is where C comes from). To force other applications into the object orientated programming paradigm is the evil plan of little bosses with strange haircuts.
Paul Graham also doesn’t like it ¹.
There’s a good base for starting a decent discussion on the Scheme Wiki ².
One good rule to follow is “collocation” – code that needs to be understood as a unit should be written as a unit. No complex source tree navigation required. Object oriented code and exceptions do just that, however.
Cleaner, more elegant and harder to recognize
(Please contact me if you want to remove your comment.)
⁂
I like object oriented programming!
I like to search, organize and use (play?) objects that make sense. No only real objects but all sorts of abstractions. Reminds me of my childhood and my construction toys. I like to have a nice self consistent object in one file with its variables so that I don’t have to check to 10 header files to see where they are defined. I like when I change a large part (a class) of my code and see that my application is still working afterward. I like when I can exchange a couple if-elsif for polymorphism (I recently done this on a bit of code written by others and found myself having real fun with it).
About your example of a search strategy, putting it into an object allows you to create alternate strategy with the same interface without changing any other part of your code, perhaps it’s possible to implement your search so that it can search among abstract objects so that the algorithm will be valid with text but also with image and later on with videos (I can imagine an interface where the objects have a match function that return a percentage or something). If you don’t like the number of source files, you can put all your class in one file (some of my colleagues do this, using Java)
Some books on object orientation I actually enjoyed very much:
I also like to hack a quick perl script, I find lisp or scheme programming challenging and fun (I feel that you need to twist your mind a little harder with lisp and that it brings back some fun in a practice where a lot of time is spend on the same boring things) and of course OO may not be the ultimate paradigm.
I admit that forcing people to use OO everywhere is not necessearly a good thing, but I also believe that there is some form of “snobism” in the way some people denigrate OO, just because it is the main thing these days.
– PierreGaston 2004-12-09 13:23 UTC
---
I was frustrated by a J2EE project when I wrote that page, so I should write something better one of these days. Back then we had like seven layers to our application (DB, entity beans, session beans, business logic, xml, xsl), so in order to change parts of the application we had to change so many things in so many different places, it was a major pain. At times I felt like we had more layers than developers on that project. Some of these layers were very boring to write (beans) and we had no code generators at hand. Deployment was crazy and complicated and error-prone. Inheritance was used to override certain aspects of default classes we used, so understanding how the final object acted required you to understand the base system, the default class, your own class, and know exactly what was overridden and why. Reasoning about the system was terribly slow.
I guess this has nothing to do with object orientation per se, but with the direction J2EE has taken...
Thanks for the pointers. Maybe I should read that book about OO and Eiffel. Always interesting to read about a new language.
Regarding your arguments, I see two main issues:
1. You seem to compare it with C (”header files”), which I don’t like either. Almost any modern language is easier to work with than C.
2. Some of your points can be made with a procedural language as well. If your search routine takes a certain number of known parameters, then you can write an alternative routine that takes the same parameters.
The only thing on your list a procedural language cannot do is polymorphism, I think. I’m not sure that feature is really important. (I’m sure it can be fun, hehe.)
– Alex Schroeder 2004-12-09 14:22 UTC
---
i can not take a position on this topic, as i hold both of your (contradictory) viewpoints at the same time.
on small toy projects, i get the good feelings with OO design that Pierre described. but at one time my employer had me working on a huge project where java complexities were maddening. i got so sick of opening dozens of small files to try to understand the reasoning and grok what was really going on. i longed for big chunks of code, and cleverness in coding rather than formalisms that gave the code a derived, mechanized look. i even suspected there must be a chain-spawner code generator, that generated these long sausage-link chains of small files.
lots of obvious talk about managing complexity probably won’t have value, so until i know what i’m talking about, i’ll just say thanks for capturing the 2 sides of the issue that fight in my head.
– GregScott 2004-12-09 16:51 UTC
---
ehe, I wrote this because I felt you were really angry against OO and trying to see the good parts of it might be helpfull at work these days.
To respond to your points
1. yes it was C header files, yes many modern languages (and some older also) are easier to read, but how many do not give OO 😉
2. You are right also, you can write in an oo way with many languages, in some aspects I think you can view oo as a redesign of procedural languages that tries to make some of the best practices more natural.
As for polymorphism, here is a small example (even if I’m sure you allready know this), of how it can be usefull, imagine that for your favorite wiki you have 2 different types of page A and B and that these types have a different header and footer. You will do something like
function printheader if type == A do print "headerA" else do print "headerB" function printfooter if type == A do print "footerA" else do print "footerB"
Now if you want to introduce a type C with yet a different header, you’ll have to modify these 2 if to add a third case. (you can use some other tricks but you will end up with 2 if or you’ll implement some form of polymorphism)
In OO you would have defined some types:
class Page function printheader function printfooter class PageA is a Page function printheader print "headerA function printfooter print "footerA" class PageB is a Page function printheader print "headerB" function printfooter print "footerB"
and then you would have done something like
if type == A do mypage = a PageA else do mypage = a PageB .... mypage.printheader .... mypage.printfooter
Then if you want to introduce a type C you only need to change the existing code in one place, as a result there are less chances to forget something. Of course this is only a trivial example but I hope it illustrates an interesting aspect of polymorphism.
Purists and gurus of all sides feel free to correct me!!
– PierreGaston 2004-12-09 19:42 UTC