Wednesday, July 25, 2012

Haskell is poorly explained

WARNING: The article below was written in a passionate wave of anger over Haskell's ponderous learning curve. I know it's logic is flawed. However, I am confident that plenty of other Haskell newbs have encountered the same issues and are also banging their head into the wall.  Since this section of the blog is about Haskell from the learner's perspective, I have decided to publish it now, and edit the salient points at a later date when the smoke of my ignorance has cleared:
 
     Most of the problems listed here (I suspect) are a result of poor documentation by all of the resources I have used so far. Having said that...

     Yes, it's true Haskell is a functional language, and as a result should not be held too strictly to the tenets of competing non-fp languages like, say ohhh, Python for instance. Python is a superbly easy language to learn from scratch (with zero CS background), and can do just about anything a programmer would ever need to do in the current professional environment. Haskell, is one of many candidates for a new ubiquitous general programming schema (functional programming) which may one day supplant the older imperative programming paradigm. In order for FP to push programming into a new direction and solve the current set of programming limitations, it needs to also do the simple things at least as well, if not better than, the current selection of popular general-purpose languages. Indeed, for it even to be considered a general-purpose language, it needs to excel at the basic level.  As such, it is assumed that Haskell (and any other good implementation of FP) can do things other languages can't do very easily or very well. It is also assumed that it will take some getting used to in order to master FP having come (as 99% of every coder on the planet has) from an imperative programming environment.

     I've been trying to keep this in mind as I develop my attitude towards Haskell as a learner and petty blogger. The problem is that this is not a valid excuse for the many problems facing anyone attempting to learn Haskell without a full-time professor, teacher's aid, or tutor on hand. I personally have begun to use freenode #haskell in lieu of such a resource. But, that is not an ideal solution. The people on #haskell are wise and generous, but they have no obligation to patiently explain things to a frustrated learner. They do so anyways (because they rock), but the IRC format itself forces all but the most blunt and carefree of folks to limit their inquiries for fear of being flamed or banned as a niuscance.

     So, that's no big deal, a good text can change all that. Haskell doesn't have a good text. But I am starting to realize, that is not the sole issue either. I am not a cultural relativist. I believe, scratch that, I know that there are some human behaviours that are right and some that are wrong. It doesn't matter if Functional Programming is based on a totally different way of thinking about problem-solving (which it isn't), there are some basic user-interface considerations that are universal and have nothing to do with the structure of the programming environment. Haskell defies some of these most basic considerations:

  • Inconsistent Syntax between interactive environments and compiler. Commands and declarations that work on Hugs don't always work on ghci and vice-versa. Commands that work in ghci and Hugs in interactive mode do not always compile. This is dumb. Plain and simple. There is no excuse. There is no point trying out program snippets in an interactive environment that gives totally different results from the compiler. That just defeats the point of even having an interactive environment. IDLE exemplifies how this can be done correctly.
  • Conflicting rules based on still more hidden laws. In Chapter 2 of Haskell: The Craft of Functional Programming we are asked to create a module which loads yet another module and uses it's code as a basis for new functions. We have previously been told that indentation is optional in Haskell. We have also been told that indentation is really just a way to make the contents of a function easier to read; and can be dispensed with at will. However, the only way to import a function inside of the definition of another function is to indent the import command, like this:                                                                                                              >module name where                                                                                                                     >    import oldmodule  
  • IO what a mess... Yes, I know Haskell IO is based on Monads which are themselves an attempt to separate impure data from pure data. Fine, I get it. But, can we at least get a listing of the reasons behind the ponderous IO mentality at work here? For example: We are told that IO actions have to be performed within a function which is, itself, an IO action. We are also told that IO actions cannot be called outside of the 'main = do' function. Then we realize (I have yet to see this documented anywhere) that certain IO actions (like getLine) cannot be called inside of 'main'. In order to bring data in from the outside world, we need to create seperate functions, each with their own 'do' notations and then call them from main. However, main handles output operations like putStrLn just fine. Why? Likewise, we are told that main, and all other 'do' notation functions must end with a function or command that returns data. Yet, some functions or commands mysteriously don't work, despite meeting all of the qualifications needed. Other functions that do work return no data whatsoever except null (). Why the inconsistency? Then there's print. Print works sometimes and then fails spectacularly at others. And, it should'nt be about type; since print has the capability to display data of all built-in types from Ints to Bools. You eventually learn to use print sometimes and putStrLn at others; often without knowing why. Why is this so hard?!
  • 'let' it be already... Declaring a variable is one of the most universal processes that occur in programming. It's the core function. In Haskell, you say 'let x = whatever'. The only problem is that let doesn't always work. For instance, try declaring a list in hugs. 'let x = [1,2,3]' doesn't work. 'x = [1,2,3]'? Nope. How the hell do you declare a stupid list? Yes, there is a way, but who cares? Why do we need to learn a 3rd way to declare a list in Hugs? We shouldn't even need to learn two ways to declare a simple variable. There should only be 1! In the time it takes to figure this out, you could be making list comprehensions in Python that already work!
  • Pointless compiler reports that even professors can't understand Why bother? If you can create a logically consistent compiler output then you can also link it to a simple pattern-matching algorithm (perhaps using Haskell's own pattern-matching toolset) that gives the user some information that is actually useful. Most of the compiler errors I have run across fall into one of four categories: 1) A function is missing an argument 2) You used the wrong type for some function or operation 3) You are missing an indent (even though indents are supposed to be voluntary). 4) You are missing parens somewhere. What's the point of even having error-messages when even the experts have a hard time understanding them?
     My point is simple: Haskell is not ready for prime-time. I'm at the point where I must choose to continue studying Haskell even though my gut is telling me that the designers never intended the language to actually be used. Thanks to LYAH, I have seen some of the ways in which Haskell can be exceptionally powerful compared to what I'm used to (Python and C++). I also know that I am an undergrad and my opinion will change once I gain mastery of the language. As a result, I am resolved to continuing my study of Haskell. 

    Still, I can already see why the language is doomed to obscurity in it's current state. It will need either massive ergonomic reform, or an exceptionally bright text to overcome it's pointlessly steep learning curve.


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.