ACM Queue: On Usability of Programming Languages

(Oldish article; I didn't yet find this posted on LtU, apologies if this turns out to be a duplicate.) If you present a consistent model of some known kind of user, other kinds of users can potentially adapt, consciously or otherwise thinking via the role of the target user. If you apply this question to C++, for example, you will find major problems.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

It is called 'inconsistencies'...

...and C++ is full of those. But how do we solve those inconsistencies? C++ has many good things, and an equal (or greater!) amount of bad things. Changing the language is one option, but when someone suggests a change, the change is ignored (see here for details). Using another language becomes a necessity, only to find out that that other language fixes the problems of C++, while not offering the goods of C++...

(I apologise for the bitterness but it seems everytime I want to program something I have to spend 90% of my time chasing solutions to impossible problems than actually doing the part that I want and that is fun, even if I use the latest and greatest programming language...)

Re: doing the fun part

I seem to have a simliar Midas Touch: I've always had trouble with O'Caml, Jython seems broken, Scala is fine but relies on the Java debugging framework which also seems broken, I personally don't like whitespace sensitivity in languages (Python, Haskell), I require a debugger (Haskell, Alice ML, Clean)...

It really makes me realize that I haven't had a "flow" moment in programming in entirely too long. I am starting to day-dream of just going back to something like a simple SML or Scheme system. (The problem there is that there are entirely too many Scheme implementations from which to choose :-)

Yeap, I know the feeling.

And after all the wasted effort, I usually feel too tired to setup yet another environment which must be just a little bit better (from what I have heard!) than the previous one...so usually I end up doing nothing!

Normally, programming should be like this:

  1. I have an idea.
  2. I open the IDE.
  3. I write the code, while at the same time developing the idea further.
  4. I compile the code.
  5. repeat steps 3-4 until the compiler does not complain anymore
  6. work done

Reality though is a little bit more like this:

  1. I have an idea.
  2. I open the C++ IDE.
  3. I write the code.
  4. I compile the code. It compiles fine.
  5. I run the program but it crashes.
  6. I then spend my days searching the reason for the crash. It is usually a "resource" problem (memory not initialized, memory management, invalid value stuffed at a variable etc)
  7. after realizing that C++ does not cut it, I delete everything and start with Java. I open the Java IDE.
  8. I write the code.
  9. I compile the code.
  10. I run the program but it still crashes, albeit not as much as in C++ this time.
  11. I then spent my days searching the reason for the crash. It is usually a "resource" problem, as in C++: a null pointer, a bad cast, etc).
  12. I fix the errors (which is usually doable as opposed to C++), then I run the program.
  13. I realize I need to change it.
  14. the important library I want to use is written in C/C++, in a manner that makes integration with Java a pain in the arse.
  15. I say to myself "no problem, forget about Java, I will use Haskell instead. After all, it allows for more productivity."
  16. I start my favorite Haskell IDE (Eclipse?).
  17. I try to write the code.
  18. since I have no easy way of mapping imperative patterns to functional, I stop writing and try to rethink about the problem.
  19. I can not find the answer, so I ask online (LtU, for example).
  20. I get no useful answer; all I get is generic talk about how Haskell is the best thing since slice bread and a few nice links which contain the knowledge I need, unfortunately, burried in many deep layers of unrelated things.
  21. having been exhausted, I give up.

Hey, maybe I am just incompenent and should give up programming altogether :(.

Other Options

First of all, you can easily map imperative patterns to functional in Haskell: that's what the State monad transformer is for. There's a good description of it here.

But the argument is a straw man: in choosing to use Haskell, you've stepped over several options that many people prefer, such as O'Caml, that have references: you can use mutation where it makes sense, algebraic data structures and pattern matching where it makes sense, objects where they make sense...

With respect to "useful answers," I have to confess that I've essentially given up trying to answer you here, because I've formed the sense that your tendency to put up straw-man arguments might not be accidental: you seem extremely resistant to good advice such as I'm giving you here, and at some point reiterating them becomes a waste of energy. If you're sincere in your search, you'd be better served by not going from one extreme (C++ with its extremely confused blend of parameteric polymorphism, inclusion polymorphism, strict evaluation, shared-state concurrency, etc.) to the other (Haskell and its lack of inclusion polymorphism, complex module system, lazy evaluation, and no mutation at all). O'Caml or Oz would be significantly better choices for you. But I have to say that I fully expect to hear why you can't use them because they don't give you Visual Studio or operator overloading or because of something else that differentiates them from C++ and many years of commercial tool development.

It's not that simple.

First of all, you can easily map imperative patterns to functional in Haskell: that's what the State monad transformer is for. There's a good description of it here.

Thanks for the link about mapping imperative patterns to functional, but my problem is not simplistic as in that article. Specifically, what I want to do is have a global object model defined in one module and apply the model-view-controller pattern of it. How can I do that with monads, given that my object model is hierrarchical and goes many levels deep, with many objects? furthermore, I want the UI to be updated as the model is modified.

But the argument is a straw man: in choosing to use Haskell, you've stepped over several options that many people prefer, such as O'Caml, that have references: you can use mutation where it makes sense, algebraic data structures and pattern matching where it makes sense, objects where they make sense...

Why not Haskell? after all I have read in many places that you can do everything with it, and that it raises your productivity 9-25 times.

With respect to "useful answers," I have to confess that I've essentially given up trying to answer you here, because I've formed the sense that your tendency to put up straw-man arguments might not be accidental: you seem extremely resistant to good advice such as I'm giving you here, and at some point reiterating them becomes a waste of energy.

I apologise if it seems that way, but pointing to a few links with articles is not "giving answers." In order to make what I want in Haskell (i.e. the model-view-controller thing I described above), I have to go through tens of sites that explain monads, applied in all sorts of algorithms, but none on how to apply monads to my problem. How does that qualify as "giving answers"?

But I have to say that I fully expect to hear why you can't use them because they don't give you Visual Studio or operator overloading or because of something else that differentiates them from C++ and many years of commercial tool development.

Oz seems like a nice language; I will have to study it further, as I did not know that it existed.

You are right about the excuses, but at least I have some pretty good arguments on things that can be off putting.

First of all, from what I have seen so far, Oz uses Emacs as the IDE. You may like Emacs, but I consider it a "bad" UI, especially when run side-by-side with something along the lines of VS2005.

Secondly, the GUI library uses QTk. Does QTk use the model-view-controller paradigm? I do not know, but it seems it does not. For example, in the listbox documentation, it says that "a listbox is a widget that displays a list of strings". Well, in good GUI libraries a list box is a view that displays a list of items that have a UI representation. Do I have to write my own code to synchronize a model and a listbox? do I have to learn how to do that in Oz? do I have to do that for every component?

Thirdly, why not have a graphical UI designer with properties etc? maybe there is one, I do not know yet. But it certainly would matter to me if I have to write all the GUI boilerplate code, as it is tedious and boring.

All these, and many more, are criteria to make me choose one development environment over the other. I will check Oz out though (you never know ;)).

Language Advocacy

For many reasons, discussed here many times at length, we should attempt not to turn LtU into a language advocacy site. Each language I can think of has forums for exactly this purpose (i.e., avocacy and help for newcomers). LtU has no edge when it comes to this sort of thing.

You are right, of course, that things like IDEs and libraries influence language usability. If someone disputed this in general, this would be a good subject for a LtU debate, but otherwise I think we can all agree that these are important factors to some degree (depending on programmer and circumsances). However, unless there's an interesting argument why you can't provide useful libraries or IDEs for a specific language, I don't see what understanding regarding general PL issues can be gained from such discussion. The only reasons I can think of are that this lack may tell us something about the language communnity, or reveal why programmers using a specific language find such tools to be less important.

The ST monad will likely

The ST monad will likely make a good starting point for you - it gives you references into a mutable polymorphic heap rather than a single mutable value as seen with the plain State monad.

If you're willing to build a wrapper around it, you can implement a good number of object models that way.

Why would you want to do

Why would you want to do object oriented programing in Haskell? Haskell is good becourse it lets you program in a functional way. If you dont do that you wouldn't get verry much out of it. Its like going from c to c++ and only write c compatible code, and complain that you don't gain anything from c++. If you must program in an object oriented style, why not do it in an object oriented language?

Re: good systems

I don't mean to sound facetious, but I'd seriously suggest VB or C# and the .Net libraries. You'll have to pay real money, but you'll get all sorts of nifty tools. (I'm more of an Emacs person myself, but I have been forced to use VS in the past and if you like that kind of thing it really isn't all that bad.)

QTk and MVC

Secondly, the GUI library uses QTk. Does QTk use the model-view-controller paradigm? I do not know, but it seems it does not.

QTk is not a replacement for MVC. What QTk offers is a compact and flexible way to define the visual structure of a GUI. It defines the static part of GUI as a nested record and the dynamic part as hooks into that. It's very easy to make an adaptable GUI in QTk: one that changes to take its environment into account (see, e.g., FlexClock and chapter 10 of CTM). It's a tool that's very easy to use, even for people who only do GUIs occasionally. It takes about 1/3 to 1/4 the number of lines to do the same interface in QTk compared to Tk (I measured it) and it's much easier to understand. QTk is implemented as an interpreter on top of Tk (one could implement a similar tool on top of any GUI library). It's very easy to use an MVC pattern with QTk, for example in an OO or in a functional style.

You have a tendency to ask

You have a tendency to ask your questions in extremely generic terms, which makes a generic answer pretty much inevitable. If you want haskell help, #haskell on irc.freenode.net is probably a better bet for you - although beware that if you show up in a bad mood you probably won't get good advice until you calm down a bit, it's not easy to teach someone who's highly frustrated.

Not too generic.

For example, the question "how to do the model-view-controller pattern" has a very specific one-line answer for Java: "you must implement the Swing's model interfaces". I expected something analogous in Haskell. Instead of that, what I got as an answer was links to monad tutorials; much appreciated, but not exactly helping in replying my question.

There are many, many ways to

There are many, many ways to implement MVC in Haskell, which is why that happened. Personally I'm fond of building an analogue using the concurrency features and a thread for each, for example. You need to provide more details - how is anyone supposed to show you MVC without knowing what your object model looks like?

Haskell MVC?

I'd also be interested to see what MVC or something similar would look like in Haskell. One way to decouple model and view is to have notifications when the model changes. For instance, Tk is largely built on variable traces that accomplish this. Does the Haskell State (or ST) monad incorporate something like this? Or is some other approach preferred?

Expectations

For example, the question "how to do the model-view-controller pattern" has a very specific one-line answer for Java: "you must implement the Swing's model interfaces".

That's a very specific one-line answer for Swing, not Java in general.

I expected something analogous in Haskell.

I think you need to adjust your expectations. If Haskell were being widely used to implement GUI applications, that would be a reasonable expectation. But Haskell is not being sold by Microsoft, Sun, Borland etc. in a shrinkwrap box with a hologram sticker on the outside.

It's not clear to me why you're drawn towards Haskell, given that it doesn't offer the level of commercial readiness that you seem to be looking for. If your goal is to write a GUI user interface, why not pick a widely-used GUI interface toolkit? The language that the back end of your application is implemented in doesn't have to be the same one which the user interface is implemented in. Neither Java nor C++ are really the best choices when it comes to developing GUIs, and nor is Haskell. None of this has any relevance to Haskell's power and productivity as a programming language, except from the perspective that a general-purpose language isn't necessarily a good choice for solving a problem that is already addressed by many canned, domain-specific toolkits.

Too Specific!

Contrary to Phillipa's observation, I would say that "How do you do MVC in Haskell?" is too specific a question. But we've already addressed this issue here on Lambda, and at this point all I would add would be to suggest that you look into Functional Reactive Programming in Haskell, or Constraint-based GUI programming in Oz.

From my point of view, you tend to get frusrated with the responses that you get—and I get frustrated giving some of them—because you really do expect direct analogies—more like isomorphisms—between C++ and Haskell or whatever, when the whole point is that there are other, and in many cases better, paradigms than what C++ offers you. So to learn why those of us who like them like them isn't going to be a matter of a week's investigation, or probably even a month's; it's going to require a real investment on your part, one that, quite frankly, I doubt you're willing to make.

With respect to IDEs, it's been said many times that there is no Visual Studio for these languages. Once again, I suspect that you'll be unsuccessful in getting past that, which is another reason, at this point, that I think this will be my last post on the subject.

Visual Haskell

With respect to IDEs, it's been said many times that there is no Visual Studio for these languages.

Err, not that I've ever tried it, but this might be what you are looking for...


Visual Haskell is a complete development environment for Haskell software, based on Microsoft's Visual Studio platform. Visual Haskell integrates with the Visual Studio editor to provide interactive features to aid Haskell development, and it enables the construction of projects consisting of multiple Haskell modules, using the Cabal building/packaging infrastructure.

Another option

Just to provide a different option instead of adding to the Haskell debate, when you reach:

after realizing that C++ does not cut it, I delete everything and start with Java. I open the Java IDE.

You can always try writing your code along with some annotations in JML which, too be honest, are largely going to be general statements about what you intend your program to do, and can help with the "...while at the same time developing the idea further" part by helping to provide clear relatively high level statements about your code. Presuming you do that much you can then change

I compile the code. It compiles fine.

into:

  1. I perform static checks on the code using ESC/Java2
  2. Repeat previous steps of writing code and statically checking until no more errors or warnings are found.

If you code passes ESC/Java2's checks it will compile fine, and those checks will catch a whole raft of errors and potential errors for you - far more than just checking whether it compiles or not could hope to find.

Because you seem IDE focussed, I will also point ou that this process is made easier by using Eclipse along with the JMLEclipse which not only provides syntax highlighting and JML integration for Eclipse, it also integrates in ESC/Java2 making the whole "statically check/find errors/correct errors" cycle no different to the usual "compile/find errors/correct errors" cycle.

It is, of course, also worth noting that if you take the time to write JML annotations as you code you can also make

I then spent my days searching the reason for the crash.

into

"I then spend a few minutes locating the location of the error based on the runtime assertion checks that were automatically inserted in when I compiled the code with the jmlc compiler."

This is, of course, not a perfect solution. Your static error checking and runtime assertion checking are only as good as the annotations you provide - but if you find yourself more comfortable with Java than with Haskell then JML and friends offer a much more friendly way to get more thorough checking for your code.

If you haven't tried it I urge you to download the relevant packages and give it a go - annotating code isn't that hard and running ESC/Java2 over such code can be a remarkably enlightening experience: it really is incredibly good at finding potential errors.

More productivity

High-level languages can increase productivity because it is easy to write. Therefore, a new language give you no benefit unless you can use it well.

Translating a program from one language to another language is usually difficult. The concepts you used in one language may be difficult to impletemented in the other language. What you need is not a simple translation, but you have to re-design or re-thing about the whole program.

Well, no

High-level languages can increase productivity because it is easy to write.

No, it doesn't work that way at all, although it's a common fallacy. Do the math. If you spend about 15% of your workday actually writing code (a very liberal estimate, 10% is closer), your productivity increase from "ease of writing" in a new language can be no more than 1.0/.85, or about 1.17x. Most likely, it'll be a lot less than that. What professional developers actually spend the bulk their time doing is testing, debugging, building, integrating, extending, deploying, and generally understanding code. To the extent that high-level languages improve productivity, it's mostly because the resulting programs are easier to understand, rather than easier to write.