3 ms·
I don't want to come out as a language troll -- I have written enough and much liked Haskell -- but one thing that Clojure, my favorite language, got right is m
by yason 17y ago
I don't want to come out as a language troll -- I have written enough and much liked Haskell -- but one thing that Clojure, my favorite language, got right is multiparadigm programming.
Because I/O is serial and imperative by nature it just so much makes sense to handle I/O in a serial and imperative way and write the rest of the program in functional style. The same can be said of state and assignments: you need persistent state at _some_ point in runtime, and I think it's best to accept the crap and be explicit about it.
I greatly appreciate the idea of monads and all the insight that went into them, but it seems to me that they were conceived merely to solve a problem that doesn't need to exist. Monads are a great academic hallelujah and I hope they lead to the discovery of some new, unfamiliar programming paradigm that benefits all programmers.
However, I think monads are currently like the various design patterns akin to the Visitor (and its relatives) in Java. People had to invent these patterns basically to emulate a plain old function pointer bundled with userdata pointer. That's an old "trick" from C in the 70's and assembly before that, but only such that is otherwise unavailable in Java.
Consequently, if you're all pure and lazy-evaluating and you decide to make that a principal issue then yes, you do need monads to do the simplest thing, such as I/O, simply to fit into the purely lazy environment. IIRC the I/O monad was where it all began -- I would be surprised to note otherwise.
Then again, what I like in Clojure is that while the program control isn't automatically lazy-evaluating I still get most of the benefits of laziness from the fact that almost all data flow in Clojure is lazy by default. I can still write these nice infinite Fibonacci series or infinite sequences of random numbers and (take) as much as I need. And I still have (delay) explicitly for any body of code that I need evaluated lazily. And I can still enjoy writing most of my code in beautiful pure functional Lisp.
Yet I _can_ still shuffle my data procedurally. And loop around I/O like a grumpy Pascal hacker in a hamster wheel as much as I want _when_ I need to. And still confine that mess into a function or two with big warning labels around, so to not contaminate the rest of my program.
I know there are people who build incredible things out of monads, or inventing monadic metatypes I'm unable to grasp, and generally doing stuff never done before.
But that is merely a sign of great cleverness of these people; the same can be said about C++ templates that you can whack into such a spaghetti that they actually run parts of your computation in compile time.
One could, I suppose, say that it's like a treadmill with wheels that are connected to the running belt but slightly downgeared: you can use it to move on a street by exercising walking with your legs but most people choose to just.. you know, walk directly.
- ramchip 17y agoMonads can be useful as an abstraction; it's more than just a somewhat convoluted way to do I/O. Look at a parser written with Parsec, or the JIT code generation that Harpy offers with monads and combinators. It's very concise and readable. I also think a major strong point of Haskell that you omitted is the type system. I've never had so few runtime errors. Which might not be saying much, since I usually program in C++ ;) but after, I admit it, a fair time spent fighting with the compiler, my experience is that when I finally get it to compile the code is correct. The purity also allows for some clever optimizations; with native code generation, Haskell is very fast. Especially if you include the JVM start time, it feels much snappier than Clojure/Java.
- a-priori 17y agoHere's an example of a parser I wrote using Parsec: http://github.com/michaelmelanson/cminus-compiler/blob/master/Compiler/Parser.hs http://github.com/michaelmelanson/cminus-compiler/blob/maste...
- plinkplonk 17y ago" I know there are people who build incredible things out of monads, or inventing monadic metatypes I'm unable to grasp, and generally doing stuff never done before. But that is merely a sign of great cleverness of these people; One could, I suppose, say that it's like a treadmill with wheels that are connected to the running belt but slightly downgeared: you can use it to move on a street by exercising walking with your legs but most people choose to just.. you know, walk directly." This is the flakiest analogy (not to say a condescending one) I've seen here in a while. The exact same argument could be made for writing a macro in Clojure vs just writing out the code in java. "yes you could write a clever macro and there are clever people doing it but other people just, you know, walk" Some programmers have trouble grasping monads. Others have trouble grasping macros. Others (believe it or not,) recursion (Ron Jeffries, an agile "guru" said "Recursive methods tend to be confusing, in my opinion." http://xprogramming.com/xpmag/dbchaskellbowling/ http://xprogramming.com/xpmag/dbchaskellbowling/), Others TCO (see Tim Bray's recent rant for e.g). When some programmers look at powerful languages they see, "merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well.". - PG on the blub paradox. Insert clojure and haskell appropriately and this sums up your argument. People who don't "get" monads and/or or how powerful type systems work think languages with those features are "weird" or "too clever" and languages without them are "better". So what's new? So yes, in spite of your " I don't want to come across as a language troll" disclaimer, you do come across as a borderline fanboi/troll. Not sayng you are one, but your argement comes across that way. Subtle condescension is still condescension. fwiw.