Getting started with Haskell - haskell

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
For a few days I've tried to wrap my head around the functional programming paradigm in Haskell. I've done this by reading tutorials and watching screencasts, but nothing really seems to stick.
Now, in learning various imperative/OO languages (like C, Java, PHP), exercises have been a good way for me to go. But since I don't really know what Haskell is capable of and because there are many new concepts to utilize, I haven't known where to start.
So, how did you learn Haskell? What made you really "break the ice"? Also, any good ideas for beginning exercises?

I'm going to order this guide by the level of skill you have in Haskell, going from an absolute beginner right up to an expert. Note that this process will take many months (years?), so it is rather long.
Absolute Beginner
Firstly, Haskell is capable of anything, with enough skill. It is very fast (behind only C and C++ in my experience), and can be used for anything from simulations to servers, guis and web applications.
However there are some problems that are easier to write for a beginner in Haskell than others. Mathematical problems and list process programs are good candidates for this, as they only require the most basic of Haskell knowledge to be able to write.
Some good guides to learning the very basics of Haskell are the Happy Learn Haskell Tutorial and the first 6 chapters of Learn You a Haskell for Great Good (or its JupyterLab adaptation). While reading these, it is a very good idea to also be solving simple problems with what you know.
Another two good resources are Haskell Programming from first principles, and Programming in Haskell. They both come with exercises for each chapter, so you have small simple problems matching what you learned on the last few pages.
A good list of problems to try is the haskell 99 problems page. These start off very basic, and get more difficult as you go on. It is very good practice doing a lot of those, as they let you practice your skills in recursion and higher order functions. I would recommend skipping any problems that require randomness as that is a bit more difficult in Haskell. Check this SO question in case you want to test your solutions with QuickCheck (see Intermediate below).
Once you have done a few of those, you could move on to doing a few of the Project Euler problems. These are sorted by how many people have completed them, which is a fairly good indication of difficulty. These test your logic and Haskell more than the previous problems, but you should still be able to do the first few. A big advantage Haskell has with these problems is Integers aren't limited in size. To complete some of these problems, it will be useful to have read chapters 7 and 8 of learn you a Haskell as well.
Beginner
After that you should have a fairly good handle on recursion and higher order functions, so it would be a good time to start doing some more real world problems. A very good place to start is Real World Haskell (online book, you can also purchase a hard copy). I found the first few chapters introduced too much too quickly for someone who has never done functional programming/used recursion before. However with the practice you would have had from doing the previous problems you should find it perfectly understandable.
Working through the problems in the book is a great way of learning how to manage abstractions and building reusable components in Haskell. This is vital for people used to object-orientated (oo) programming, as the normal oo abstraction methods (oo classes) don't appear in Haskell (Haskell has type classes, but they are very different to oo classes, more like oo interfaces). I don't think it is a good idea to skip chapters, as each introduces a lot new ideas that are used in later chapters.
After a while you will get to chapter 14, the dreaded monads chapter (dum dum dummmm). Almost everyone who learns Haskell has trouble understanding monads, due to how abstract the concept is. I can't think of any concept in another language that is as abstract as monads are in functional programming. Monads allows many ideas (such as IO operations, computations that might fail, parsing,...) to be unified under one idea. So don't feel discouraged if after reading the monads chapter you don't really understand them. I found it useful to read many different explanations of monads; each one gives a new perspective on the problem. Here is a very good list of monad tutorials. I highly recommend the All About Monads, but the others are also good.
Also, it takes a while for the concepts to truly sink in. This comes through use, but also through time. I find that sometimes sleeping on a problem helps more than anything else! Eventually, the idea will click, and you will wonder why you struggled to understand a concept that in reality is incredibly simple. It is awesome when this happens, and when it does, you might find Haskell to be your favorite imperative programming language :)
To make sure that you are understanding Haskell type system perfectly, you should try to solve 20 intermediate haskell exercises. Those exercises using fun names of functions like "furry" and "banana" and helps you to have a good understanding of some basic functional programming concepts if you don't have them already. Nice way to spend your evening with a bunch of papers covered with arrows, unicorns, sausages and furry bananas.
Intermediate
Once you understand Monads, I think you have made the transition from a beginner Haskell programmer to an intermediate haskeller. So where to go from here? The first thing I would recommend (if you haven't already learnt them from learning monads) is the various types of monads, such as Reader, Writer and State. Again, Real world Haskell and All about monads gives great coverage of this. To complete your monad training learning about monad transformers is a must. These let you combine different types of Monads (such as a Reader and State monad) into one. This may seem useless to begin with, but after using them for a while you will wonder how you lived without them.
Now you can finish the real world Haskell book if you want. Skipping chapters now doesn't really matter, as long as you have monads down pat. Just choose what you are interested in.
With the knowledge you would have now, you should be able to use most of the packages on cabal (well the documented ones at least...), as well as most of the libraries that come with Haskell. A list of interesting libraries to try would be:
Parsec: for parsing programs and text. Much better than using regexps. Excellent documentation, also has a real world Haskell chapter.
QuickCheck: A very cool testing program. What you do is write a predicate that should always be true (eg length (reverse lst) == length lst). You then pass the predicate the QuickCheck, and it will generate a lot of random values (in this case lists) and test that the predicate is true for all results. See also the online manual.
HUnit: Unit testing in Haskell.
gtk2hs: The most popular gui framework for Haskell, lets you write gtk applications.
happstack: A web development framework for Haskell. Doesn't use databases, instead a data type store. Pretty good docs (other popular frameworks would be snap and yesod).
Also, there are many concepts (like the Monad concept) that you should eventually learn. This will be easier than learning Monads the first time, as your brain will be used to dealing with the level of abstraction involved. A very good overview for learning about these high level concepts and how they fit together is the Typeclassopedia.
Applicative: An interface like Monads, but less powerful. Every Monad is Applicative, but not vice versa. This is useful as there are some types that are Applicative but are not Monads. Also, code written using the Applicative functions is often more composable than writing the equivalent code using the Monad functions. See Functors, Applicative Functors and Monoids from the learn you a haskell guide.
Foldable,Traversable: Typeclasses that abstract many of the operations of lists, so that the same functions can be applied to other container types. See also the haskell wiki explanation.
Monoid: A Monoid is a type that has a zero (or mempty) value, and an operation, notated <> that joins two Monoids together, such that x <> mempty = mempty <> x = x and x <> (y <> z) = (x <> y) <> z. These are called identity and associativity laws. Many types are Monoids, such as numbers, with mempty = 0 and <> = +. This is useful in many situations.
Arrows: Arrows are a way of representing computations that take an input and return an output. A function is the most basic type of arrow, but there are many other types. The library also has many very useful functions for manipulating arrows - they are very useful even if only used with plain old Haskell functions.
Arrays: the various mutable/immutable arrays in Haskell.
ST Monad: lets you write code with a mutable state that runs very quickly, while still remaining pure outside the monad. See the link for more details.
FRP: Functional Reactive Programming, a new, experimental way of writing code that handles events, triggers, inputs and outputs (such as a gui). I don't know much about this though. Paul Hudak's talk about yampa is a good start.
There are a lot of new language features you should have a look at. I'll just list them, you can find lots of info about them from google, the haskell wikibook, the haskellwiki.org site and ghc documentation.
Multiparameter type classes/functional dependencies
Type families
Existentially quantified types
Phantom types
GADTS
others...
A lot of Haskell is based around category theory, so you may want to look into that. A good starting point is Category Theory for Computer Scientist. If you don't want to buy the book, the author's related article is also excellent.
Finally you will want to learn more about the various Haskell tools. These include:
ghc (and all its features)
cabal: the Haskell package system
darcs: a distributed version control system written in Haskell, very popular for Haskell programs.
haddock: a Haskell automatic documentation generator
While learning all these new libraries and concepts, it is very useful to be writing a moderate-sized project in Haskell. It can be anything (e.g. a small game, data analyser, website, compiler). Working on this will allow you to apply many of the things you are now learning. You stay at this level for ages (this is where I'm at).
Expert
It will take you years to get to this stage (hello from 2009!), but from here I'm guessing you start writing phd papers, new ghc extensions, and coming up with new abstractions.
Getting Help
Finally, while at any stage of learning, there are multiple places for getting information. These are:
the #haskell irc channel
the mailing lists. These are worth signing up for just to read the discussions that take place - some are very interesting.
other places listed on the haskell.org home page
Conclusion
Well this turned out longer than I expected... Anyway, I think it is a very good idea to become proficient in Haskell. It takes a long time, but that is mainly because you are learning a completely new way of thinking by doing so. It is not like learning Ruby after learning Java, but like learning Java after learning C. Also, I am finding that my object-orientated programming skills have improved as a result of learning Haskell, as I am seeing many new ways of abstracting ideas.

Some colleague of mine had good experience with Learn You a Haskell for Great Good!.
Tutorial aimed at people who have
experience in imperative programming
languages but haven't programmed in a
functional language before.
And check the answers here too

Here's a good book that you can read online: Real World Haskell
Most of the Haskell programs I've done have been to solve Project Euler problems.
Once piece of advice I read not too long ago was that you should have a standard set of simple problems you know how to solve (in theory) and then whenever you try to learn a new language you implement those problems in that language.

I enjoyed watching this 13 episode series on Functional Programming using Haskell.
C9 Lectures: Dr. Erik Meijer - Functional Programming Fundamentals:
http://channel9.msdn.com/shows/Going+Deep/Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1/

To add on others' answers - there is one useful that will help you when coding (for example when solving project Euler problems):
Hoogle. You can use either the command line interface or the web interface.
Command Line
After you installed the Haskell platform be sure to cabal install hoogle
Hoogle usage example:
You have a function f x = 3 * x + 1 and you want to apply it on (5 :: Int), then apply it on the result and on that result and so on and get an infinite list of those values. You suspect there might already exist a function to assist you (not specifically for your f though).
That function would be of type (a -> a) -> a -> [a] if it takes f 5 or a -> (a -> a) -> [a] if it takes 5 f (we assume the function is for general types and not just Ints)
$ hoogle "a -> (a -> a) -> [a]"
Prelude iterate :: (a -> a) -> a -> [a]
yep, the function you need already exists and it's called iterate. you use it by iterate func 5!
Web interface
The result for the same example can be found here.

Graham Hutton's Programming in Haskell is concise, reasonably thorough, and his years of teaching Haskell really show. It's almost always what I recommend people start with, regardless of where you go from there.
In particular, Chapter 8 ("Functional Parsers") provides the real groundwork you need to start dealing with monads, and I think is by far the best place to start, followed by All About Monads. (With regard to that chapter, though, do note the errata from the web site, however: you can't use the do form without some special help. You might want to learn about typeclasses first and solve that problem on your own.)
This is rarely emphasized to Haskell beginners, but it's worth learning fairly early on not just about using monads, but about constructing your own. It's not hard, and customized ones can make a number of tasks rather more simple.

Don't try to read all the monad tutorials with funny metaphors. They will just get you mixed up even worse.

I'd suggest joining the #haskell irc channel and asking questions there. That's how I learned Haskell. If you go through Real World Haskell as suggested above, real time answers to your questions will help greatly. Lots of smart people on #haskell write Haskell for fun and for profit, so you'll get lots of good input. Try it!

These are my favorite
Haskell: Functional Programming with Types
Joeri van Eekelen, et al. | Wikibooks
Published in 2012, 597 pages
Real World Haskell
B. O'Sullivan, J. Goerzen, D. Stewart | OReilly Media, Inc.
Published in 2008, 710 pages

I can additionally recommend Yet Another Haskell Tutorial as an introduction.
Another good learning resource (probably on the intermediate level), which has helped me a lot and hasn't been mentioned in the other answers as far as I can see, is Brent Yorgey's Typeclassopedia, which can be found in The Monad Reader (Issue 13)
It is written in a very accessible style and contains (among many other things), the following introductory advice:
There are two keys to an expert Haskell hacker’s wisdom:
Understand the types.
Gain a deep intuition for each type class and its relationship to other
type classes, backed up by familiarity with many examples.
The Monad Reader itself is an absolute treasure trove for functional programmers (not only Haskell programmers).

Try writing easy programs in it.
You can find sample tasks in various textbooks, probably.
I wouldn't recommend sticking to Haskell/FP textbooks, just try to do simple things with it: calculations, string manipulations, file access.
After I solved a dozen, I've broke the ice :)
After that, read a lot on advanced concepts (Monads, Arrows, IO, recursive data structures), because haskell is infinite and there are a lot of them.

I do think that realizing Haskell's feature by examples is the best way to start above all.
http://en.wikipedia.org/wiki/Haskell_98_features
Here is tricky typeclasses including monads and arrows
http://www.haskell.org/haskellwiki/Typeclassopedia
for real world problems and bigger project, remember these tags: GHC(most used compiler), Hackage(libraryDB), Cabal(building system), darcs(another building system).
A integrated system can save your time: http://hackage.haskell.org/platform/
the package database for this system: http://hackage.haskell.org/
GHC compiler's wiki: http://www.haskell.org/haskellwiki/GHC
After Haskell_98_features and Typeclassopedia, I think you already can find and read the documention about them yourself
By the way, you may want to test some GHC's languages extension which may be a part of haskell standard in the future.
this is my best way for learning haskell. i hope it can help you.

I suggest that you first start by reading BONUS' tutorial, And then reading Real World Haskell (online for free). Join the #Haskell IRC channel, on irc.freenode.com, and ask questions. These people are absolutely newbie friendly, and have helped me a lot over time. Also, right here on SO is a great place to get help with things you can't grasp! Try not to get discouraged, once it clicks, your mind will be blown.
BONUS' tutorial will prime you up, and get you ready for the thrill ride that Real World Haskell brings. I wish you luck!

If you only have experience with imperative/OO languages, I suggest using a more conventional functional language as a stepping stone. Haskell is really different and you have to understand a lot of different concepts to get anywhere. I suggest tackling a ML-style language (like e.g. F#) first.

The first answer is a very good one. In order to get to the Expert level, you should do a PhD with some of the Experts themselves.
I suggest you to visit the Haskell page: http://haskell.org. There you have a lot of material, and a lot of references to the most up-to-date stuff in Haskell, approved by the Haskell community.

Related

What is Crockford's law?

Someone referenced "Crockford's law" recently with respect to monads. Google shows very little in the way of results. Anyone know what it is?
Assuming "Crockford's Law" is The Curse that he mentions early in the video, he's referring to this common occurrence (described much more eloquently here):
person X doesn't understand monads
person X works long and hard, and groks monads
person X experiences amazing feeling of enlightenment, wonders why others are not similarly enlightened
person X gives horrible, incomplete, inaccurate, oversimplified, and confusing explanation of monads to others which probably makes them think that monads are stupid, dumb, worthless, overcomplicated, unnecessary, something incorrect, or a mental wank-ercise
Here's are some of the reasons why I think The Curse exists:
forgetting how different functional programming is from so-called "mainstream" programming. If you don't already have a good understanding of what FP is, and why people do it, things built using FP won't make sense. Such things take time and effort
forgetting how different capturing effects as first-class citizens is from effects provided by the system (exceptions or mutable state, for example): same as above
lack of good motivating examples. You know, stuff like "this is the problem, here's the typical solution, but oh wait, the typical solution has these problems so let's see how we can cleanly fix those using monads!" That's a lot more work than the tired old example about null pointer exceptions
forgetting what a monad provides -- lots of "monad" examples I see actually work just fine as Functor or Applicative Functor examples
forgetting that monads are built within Haskell. Question: if monads suddenly disappeared, would you still be able to do I/O in Haskell?
thinking that monads require syntactic support, or a certain type system
thinking that monads are only about mutable state or I/O
I have fallen victim to The Curse. :(
It sounds like Crockford has as well, based on one of the questions at the end: "so monads are basically just the Builder pattern?" IMHO, it's a great video for learning kick-ass Javascript techniques, but not so great if you actually want to learn about monads.
If you are trying to learn about monads, just put in the time and effort and do lots of examples. Reimplement all the monad instances and combinators from scratch. Eventually you will be in a position to fall victim to The Curse as well!
(alternate link)
Crockford conundrum - the inability of Haskell beginners to help other Haskell beginners to understand monads, before or after they understand it themselves; the phenomenon typically seen in Haskell beginners who have been trying to figure out how to print "Hello, world!". Occasionally offered up as proof of the futility of presenting Haskell beginners with a model of I/O relying on an abstract data type (A.D.T.) whose interface is based on "one of the most abstract branches of mathematics". Sometimes given as one reason for teaching JavaScript in introductory courses instead of Haskell. Rumoured to be under consideration for inclusion to the Millennium problems by The Clay Institute of Mathematics.
Alternate names: Crockford complex, Crockford's law.

Recursion schemes for dummies?

I'm looking for some really simple, easy-to-grasp explanations of recursion schemes and corecursion schemes (catamorphisms, anamorphisms, hylomorphisms etc.) which do not require following lots of links, or opening a category theory textbook. I'm sure I've reinvented many of these schemes unconsciously and "applied" them in my head during the process of coding (I'm sure many of us have), but I have no clue what the (co)recursion schemes I use are called. (OK, I lied. I've just been reading about a few of them, which prompted this question. But before today, I had no clue.)
I think diffusion of these concepts within the programming community has been hindered by the forbidding explanations and examples one tends to come across - for example on Wikipedia, but also elsewhere.
It's also probably been hindered by their names. I think there are some alternative, less mathematical names (something about bananas and barbed wire?) but I have no clue what the cutsier names are for recursion schemes that I use, either.
I think it would help to use examples with datatypes representing simple real-world problems, rather than abstract data types such as binary trees.
Extremely loosely speaking, a catamorphism is just a slight generalization of fold, and an anamorphism is a slight generalization of unfold. (And a hylomorphism is just an unfold followed by a fold.). They're presented in a more rigorous form usually, to make the connection to category theory clearer. The denser form lets us distinguish data (the necessarily finite product of an initial algebra) and codata (the possibly infinite product of a final coalgebra). This distinction lets us guarantee that a fold is never called on an infinite list. The other reason for the funny way that catamorphisms and anamorphisms are generally written is that by operating over F-algebras and F-coalgebras (generated from functors) we can write them once and for all, rather than once over a list, once over a binary tree, etc. This in turn helps make clear exactly why they're all the same thing.
But from a pure intuition standpoint, you can think of cata and ana as reducing and producing, and that's about it.
Edit: a bit more
A metamorphism (Gibbons) is like an inside-out hylo -- its a fold followed by an unfold. So you can use it to tear down a stream and build up a new one with a potentially different structure.
Ekmett posted a nice "field guide" to the various schemes in the literature: http://comonad.com/reader/2009/recursion-schemes/
However, while the "intuitive" explanations are straightforward, the linked code is less so, and the blog posts on some of these might be a tad on the complex/forbidding side.
That said, except perhaps for histomorphisms I don't think the rest of the zoo is necessarily something you'd want to think with directly most of the time. If you "get" hylo and meta, you can express nearly anything in terms of them alone. Typically the other morphisms are more restrictive, not less (but therefore give you more properties "for free").
A few references, from the most category-theoretic (but relevant to give a "territory map" that will let you avoid "clicking lots of links") to the simpler & more self-contained:
As far as the "bananas & barbed wire" vocabulary goes, this comes from the original paper of Meijer, Fokkinga & Patterson (and its sequel by other authors), and it is in sum just as notation-heavy as the less cute alternatives : the "names" (bananas, etc) are just a shortcut to the graphical appearance of the ascii notation of the constructions they are pegged to. For example, catamorphisms (i.e. folds) are represented with (| _ |), and the par-with-parenthesis looks like a "banana", hence the name. This is the paper who is most often called "impenetrable", hence not the first thing I'd look up if I were you.
The basic reference for those recursion schemes (or more precisely, for a relational approach to those recursion schemes) is Bird & de Moor's Algebra of Programming (the book is unavailable except as a print-on demand, but there are copies available second-hand & it should be in libraries). It contains a more paced & detailed explanation of point-free programming, if still "academic" : the book introduces some category-theoretic vocabulary, though in a self-contained manner. Yet, the exercises (that you wouldn't find in a paper) help.
Sorting morphisms by Lex Augustjein, uses sorting algorithms on various data structures to explain recursion schemes. It is pretty much "recursion schemes for dummies" by construction:
This presentation gives the opportunity to introduce the various morphisms in
a simple way, namely as patterns of recursion that are useful in functional programming, instead of the usual approach via category theory, which tends to be needlessly intimidating for the average programmer.
Another approach to making a symbols-free presentation is Jeremy Gibbons' chapter Origami Programming in The Fun of Programming, with some overlap with the previous one. Its bibliography gives a tour of the introductions to the topic.
Edit : Jeremy Gibbons just let me know he has added a link to the bibliography of the whole book on the book's webpage after reading this question. Enjoy !
I'm afraid these last two references only give a solid explanation of (cata|ana|hylo|para)morphisms, but my hope is that this would be enough to tear through the algebraic formalism you can find in more notation-heavy publications. I don't know of any strictly non-category-theoretic explanation of (co-)recursion schemes other than those four.
Tim Williams gave a brilliant talk at the London Haskell User Group last night about recursion schemes with a motivating example of each of the ones you mention. Check out the slides:
http://www.timphilipwilliams.com/slides.html
There are references to all the usual suspects (lenses, bananas, barbed wire ala carte etc) at the end of the slides and you could also google "Origami Programming" which is a nice intro that I hadn't come across before.
and the video will be here when it's uploaded:
http://www.youtube.com/user/LondonHaskell
edit Most of the links in question are in huitseeker's answer above.

Is there any Template Haskell tutorial for someone who doesn't know Lisp?

I wanted to learn Template Haskell but all tutorials I find either assume that you learned lisp and know what lisp macros are, or that you know some cs theory jargon - things as splices, quasiquotations, etc... - or some theoretical results about macros.
I can't code a single line of lisp (and, though I intend to do this some day, I don't have the time to learn it right now). Haskell is my very first functional language and I learned it to the point that I can regularly code in it, use monads, applicative, understand the type system, etc... but I don't know much (also want to learn but I'm too stupid for it... :P) about the theoretical cs stuff behind it. So I'm oblivious to the jargon I typically find on TH tutorials.
So, the question is: is there a tutorial about TH for someone who code Haskell, not as a professional computer scientist, but just as a guy who uses programming for his daily chores, who learned Haskell as his first functional language? Maybe a introduction to macros and meta-programming that use TH as example?
Thanks all. :)
No, I don't think there are any great introductory tutorials to Template Haskell. The best way to learn is to look at examples, or:
First stab at Template Haskell
The user's manual
Igloo's paper :: PS
I never found Lisp was a requirement, however there is terminology to learn, like for any domain-specific library.
The best introductory tutorials to Template Haskell I know of are two documents by Bulat Ziganshin. The links from the Haskell Wiki seem to be broken at the moment, however you can access them via archive.org:
TH Tutorial
TH Documentation explanation
Also the original paper Template metaprogramming for Haskell by Tim Sheard and Simon Peyton Jones might be helpful:
Abstract
We propose a new extension to the purely functional programming language Haskell that supports compile-time meta-programming. The purpose of the system is to support the algorithmic construction of programs at compile-time.
The ability to generate code at compile time allows the programmer to implement such features as polytypic programs, macro-like expansion, user directed optimization (such as inlining), and the generation of supporting data structures and functions from existing data structures and functions.
Our design is being implemented in the Glasgow Haskell Compiler, ghc.

What language to learn after Haskell? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
As my first programming language, I decided to learn Haskell. I'm an analytic philosophy major, and Haskell allowed me to quickly and correctly create programs of interest, for instance, transducers for natural language parsing, theorem provers, and interpreters. Although I've only been programming for two and a half months, I found Haskell's semantics and syntax much easier to learn than more traditional imperative languages, and feel comfortable (now) with the majority of its constructs.
Programming in Haskell is like sorcery, however, and I would like to broaden my knowledge of programming. I would like to choose a new programming language to learn, but I do not have enough time to pick up an arbitrary language, drop it, and repeat. So I thought I would pose the question here, along with several stipulations about the type of language I am looking for. Some are subjective, some are intended to ease the transition from Haskell.
Strong type system. One of my favorite parts of programming in Haskell is writing type declarations. This helps structure my thoughts about individual functions and their relationship to the program as a whole. It also makes informally reasoning about the correctness of my program easier. I'm concerned with correctness, not efficiency.
Emphasis on recursion rather than iteration. I use iterative constructs in Haskell, but implement them recursively. However, it is much easier to understand the structure of a recursive function than a complicated iterative procedure, especially when using combinators and higher-order functions like maps, folds and bind.
Rewarding to learn. Haskell is a rewarding language to work in. It's a little like reading Kant. My experience several years ago with C, however, was not. I'm not looking for C. The language should enforce a conceptually interesting paradigm, which in my entirely subjective opinion, the C-likes do not.
Weighing the answers: These are just notes, of course. I'd just like to reply to everyone who gave well-formed responses. You have been very helpful.
1) Several responses indicated that a strong, statically typed language emphasizing recursion means another functional language. While I want to continue working strongly with Haskell, camccann and larsmans correctly pointed out that another such language would "ease the transition too much." These comments have been very helpful, because I am not looking to write Haskell in Caml! Of the proof assistants, Coq and Agda both look interesting. In particular, Coq would provide a solid introduction to constructive logic and formal type theory. I've spent a little time with first-order predicate and modal logic (Mendellsohn, Enderton, some of Hinman), so I would probably have a lot of fun with Coq.
2) Others heavily favored Lisp (Common Lisp, Scheme and Clojure). From what I gather, both Common Lisp and Scheme have excellent introductory material (On Lisp and The Reasoned Schemer, SICP). The material in SICP causes me to lean towards Scheme. In particular, Scheme through SICP would cover a different evaluation strategy, the implementation of laziness, and a chance to focus on topics like continuations, interpreters, symbolic computation, and so on. Finally, as others have pointed out, Lisp's treatment of code/data would be entirely new. Hence, I am leaning heavily towards option (2), a Lisp.
3) Third, Prolog. Prolog has a wealth of interesting material, and its primary domain is exactly the one I'm interested in. It has a simple syntax and is easy to read. I can't comment more at the moment, but after reading an overview of Prolog and skimming some introductory material, it ranks with (2). And it seems like Prolog's backtracking is always being hacked into Haskell!
4) Of the mainstream languages, Python looks the most interesting. Tim Yates makes the languages sound very appealing. Apparently, Python is often taught to first-year CS majors; so it's either conceptually rich or easy to learn. I'd have to do more research.
Thank you all for your recommendations! It looks like a Lisp (Scheme, Clojure), Prolog, or a proof assistant like Coq or Agda are the main langauages being recommended.
I would like to broaden my knowledge of programming. (...) I thought I would pose the question here, along with several stipulations about the type of language I am looking for. Some are subjective, some are intended to ease the transition from Haskell.
Strong type system. (...) It also makes informally reasoning about the correctness of my program easier. I'm concerned with correctness, not efficiency.
Emphasis on recursion rather than iteration. (...)
You may be easing the transition a bit too much here, I'm afraid. The very strict type system and purely functional style are characteristic of Haskell and pretty much anything resembling a mainstream programming language will require compromising at least somewhat on one of these. So, with that in mind, here are a few broad suggestions aimed at retaining most of what you seem to like about Haskell, but with some major shift.
Disregard practicality and go for "more Haskell than Haskell": Haskell's type system is full of holes, due to nontermination and other messy compromises. Clean up the mess and add more powerful features and you get languages like Coq and Agda, where a function's type contains a proof of its correctness (you can even read the function arrow -> as logical implication!). These languages have been used for mathematical proofs and for programs with extremely high correctness requirements. Coq is probably the most prominent language of the style, but Agda has a more Haskell-y feel (as well as being written in Haskell itself).
Disregard types, add more magic: If Haskell is sorcery, Lisp is the raw, primal magic of creation. Lisp-family languages (also including Scheme and Clojure) have nearly unparalleled flexibility combined with extreme minimalism. The languages have essentially no syntax, writing code directly in the form of a tree data structure; metaprogramming in a Lisp is easier than non-meta programming in some languages.
Compromise a bit and move closer to the mainstream: Haskell falls into the broad family of languages influenced heavily by ML, any of which you could probably shift to without too much difficulty. Haskell is one of the strictest when it comes to correctness guarantees from types and use of functional style, where others are often either hybrid styles and/or make pragmatic compromises for various reasons. If you want some exposure to OOP and access to lots of mainstream technology platforms, either Scala on the JVM or F# on .NET have a lot in common with Haskell while providing easy interoperability with the Java and .NET platforms. F# is supported directly by Microsoft, but has some annoying limitations compared to Haskell and portability issues on non-Windows platforms. Scala has direct counterparts to more of Haskell's type system and Java's cross-platform potential, but has a more heavyweight syntax and lacks the powerful first-party support that F# enjoys.
Most of those recommendations are also mentioned in other answers, but hopefully my rationale for them offers some enlightenment.
I'm going to be That Guy and suggest that you're asking for the wrong thing.
First you say that you want to broaden your horizons. Then you describe the kind of language that you want, and its horizons sound incredibly like the horizons you already have. You're not going to gain very much by learning the same thing over and over.
I would suggest you learn a Lisp — i.e. Common Lisp, Scheme/Racket or Clojure. They're all dynamically typed by default, but feature some sort of type hinting or optional static typing. Racket and Clojure are probably your best bets.
Clojure is more recent and has more Haskellisms like immutability by default and lots of lazy evaluation, but it's based on the Java Virtual Machine, which means it has some odd warts (e.g. the JVM doesn't support tail call elimination, so recursion is kind of a hack).
Racket is much older, but has picked up a lot of power along the way, such as static type support and a focus on functional programming. I think you'd probably get the most out of Racket.
The macro systems in Lisps are very interesting and vastly more powerful than anything you'll see anywhere else. That alone is worth at least looking at.
From the standpoint of what suits your major, the obvious choice seems like a logic language such as Prolog or its derivatives. Logic programming can be done very neatly in a functional language (see, e.g. The Reasoned Schemer) , but you might enjoy working with the logic paradigm directly.
An interactive theorem proving system such as twelf or coq might also strike your fancy.
I'd advise you learn Coq, which is a powerful proof assistant with syntax that will feel comfortable to the Haskell programmer. The cool thing about Coq is it can be extracted to other functional languages, including Haskell. There is even a package (Meldable-Heap) on Hackage that was written in Coq, had properties proven about its operation, then extracted to Haskell.
Another popular language that offers more power than Haskell is Agda - I don't know Agda beyond knowing it is dependently typed, on Hackage, and well respected by people I respect, but those are good enough reasons to me.
I wouldn't expect either of these to be easy. But if you know Haskell and want to move forward to a language that gives more power than the Haskell type system then they should be considered.
As you didn't mention any restrictions besides your subjective interests and emphasize 'rewarding to learn' (well, ok, I'll ignore the static typing restriction), I would suggest to learn a few languages of different paradigms, and preferably ones which are 'exemplary' for each of them.
A Lisp dialect for the code-as-data/homoiconicity thing and because they are good, if not the best, examples of dynamic (more or less strict) functional programming languages
Prolog as the predominant logic programming language
Smalltalk as the one true OOP language (also interesting because of its usually extremely image-centric approach)
maybe Erlang or Clojure if you are interested in languages forged for concurrent/parallel/distributed programming
Forth for stack oriented programming
(Haskell for strict functional statically typed lazy programming)
Especially Lisps (CL not as much as Scheme) and Prolog (and Haskell) embrace recursion.
Although I am not a guru in any of these languages, I did spend some time with each of them, except Erlang and Forth, and they all gave me eye-opening and interesting learning experiences, as each one approaches problem solving from a different angle.
So, though it may seem as if I ignored the part about your having no time to try a few languages, I rather think that time spent with any of these will not be wasted, and you should have a look at all of them.
How about a stack-oriented programming language? Cat hits your high points. It is:
Statically typed with type inference.
Makes you re-think common imperative languages concepts like looping. Conditional execution and looping are handled with combinators.
Rewarding - forces you to understand yet another model of computation. Gives you another way to think about and decompose problems.
Dr. Dobbs published a short article about Cat in 2008 though the language has changed slightly.
If you want a strong(er)ly typed Prolog, Mercury is an interesting choice. I've dabbled in it in the past and I liked the different perspective it gave me. It also has moded-ness (which parameters need to be free/fixed) and determinism (how many results are there?) in the type system.
Clean is very similar to Haskell, but has uniqueness typing, which are used as an alternative to Monads (more specifically, the IO monad). Uniqueness typing also does interesting stuff to working with arrays.
I'm a bit late but I see that no one has mentioned a couple of paradigms and related languages that can interest you for their high-level of abstraction and generality:
rewriting systems, like Maude or ELAN;
Constraint Handling Rules (CHR).
Despite its failure to meet one of your big criteria (static* typing), I'm going to make a case for Python. Here are a few reasons I think you should take a look at it:
For an imperative language, it is surprisingly functional. This was one of the things that struck me when I learned it. Take list comprehensions, for example. It has lambdas, first-class functions, and many functionally-inspired compositions on iterators (maps, folds, zips...). It gives you the option of picking whatever paradigm suits the problem best.
IMHO, it is, like Haskell, beautiful to code in. The syntax is simple and elegant.
It has a culture that focuses on doing things in a straightforward way, rather than focusing too minutely on efficiency.
I understand if you are looking for something else though. Logic programming, for instance, might be right up your alley, as others have suggested.
* I assume you mean static typing here, since you want to declare the types. Techincally, Python is a strongly typed language, since you can't arbitrarily interpret, say, a string as an number. Interestingly, there are Python derivatives that allow static typing, like Boo.
I would recommend you Erlang. It is not strong typed language and you should try it. It is very different approach to programming and you may find that there are problems where strong typing is not The Best Tool(TM). Anyway Erlang provides you tools for static type verification (typer, dialyzer) and you can use strong typing on parts where you gain benefits from it. It can be interesting experience for you but be prepared, it will be very different feeling. If you are looking for "conceptually interesting paradigm" you can found them in Erlang, message passing, memory separation instead sharing, distribution, OTP, error handling and error propagation instead of error "prevention" and so. Erlang can be far away from your current experience but still brain tickling if you have experience with C and Haskell.
Given your description, I would suggest Ocaml or F#.
The ML family are generally very good in terms of a strong type system. The emphasis on recursion, coupled with pattern matching, is also clear.
Where I am a bit hesitant is on the rewarding to learn part. Learning them was rewarding for me, no doubt. But given your restrictions and your description of what you want, it seems you are not actually looking for something much more different than Haskell.
If you didn't put your restrictions I would have suggested Python or Erlang, both of which would take you out of your comfort zone.
In my experience, strong typing + emphasis on recursion means another functional programming language. Then again, I wonder if that's very rewarding, given that none of them will be as "pure" as Haskell.
As other posters have suggested, Prolog and Lisp/Scheme are nice, even though both are dynamically typed. Many great books with a strong theoretical "taste" to them have been published about Scheme in particular. Take a look at SICP, which also conveys a lot of general computer science wisdom (meta-circular interpreters and the like).
Factor will be a good choice.
You could start looking into Lisp.
Prolog is a cool language too.
If you decide to stray from your preference for a type system,you might be interested in the J programming language. It is outstanding for how it emphasizes function composition. If you like point-free style in Haskell, the tacit form of J will be rewarding. I've found it extraordinarily thought-provoking, especially with regard to semantics.
True, it doesn't fit your preconceptions as to what you'd like, but give it a look. Just knowing that it's out there is worth discovering. The sole source of complete implementations is J Software, jsoftware.com.
Go with one of the main streams. Given the resources available, future marketability of your skill, rich developer ecosystem I think you should start with either Java or C#.
Great question-- I've been asking it myself recently after spending several months thoroughly enjoying Haskell, although my background is very different (organic chemistry).
Like you, C and its ilk are out of the question.
I've been oscillating between Python and Ruby as the two practical workhorse scripting languages today (mules?) that both have some functional components to them to keep me happy. Without starting any Rubyist/Pythonist debates here, but my personal pragmatic answer to this question is:
Learn the one (Python or Ruby) that you first get an excuse to apply.

Is Haskell suitable as a first language?

I have had previous exposure to imperative languages (C, some Java) however I would say I had no experience in programming. Therefore: treating me as a non-programmer, would Haskell be suitable as a first language?
My interests in Pure Mathematics and CS seem to align to the intention of most Haskell tutorials, and although i can inherently recognise the current and future industry value of imperative programming, I find the potential of functional programming (in as much as it seems such a paradigm shift) fascinating.
I guess my question can be distilled as follows - would a non-programmer have to understand imperative programming to appreciate and fully utilise functional programming?
Some references:
Are there any studies on whether functional/declarative or imperative programming is easier to learn as a first language?
Which programming languages have helped you to understand programming better?
Well, the existence of SICP suggests that functional languages can be used as introductory material. Scheme is perhaps more approachable than Haskell, however.
Haskell seems to have a reputation for being "difficult" to learn, but people tend to forget that classic imperative programming is difficult to learn as well. Many people struggle at first with the concept of assigning a value to a variable, and a surprising number of programmers never actually do become comfortable with pointers and indirect references.
The connections between Haskell and abstract mathematics don't really matter as much as people sometimes assume, but for someone interested in the math anyway, looking at the analogies might provide an interesting bonus.
There has been at least one study on the effects of teaching Haskell to beginner programmers:
The Risks and Benefits of Teaching Purely Functional Programming in First Year. Manuel M. T. Chakravarty and Gabriele Keller. Journal of Functional Programming 14(1), pp 113-123, 2004.
With the following abstract:
We argue that teaching purely
functional programming as such in
freshman courses is detrimental to
both the curriculum as well as to
promoting the paradigm. Instead, we
need to focus on the more general aims
of teaching elementary techniques of
programming and essential concepts of
computing. We support this viewpoint
with experience gained during several
semesters of teaching large first-year
classes (up to 600 students) in
Haskell. These classes consisted of
computer science students as well as
students from other disciplines. We
have systematically gathered student
feedback by conducting surveys after
each semester. This article
contributes an approach to the use of
modern functional languages in first
year courses and, based on this,
advocates the use of functional
languages in this setting.
So, yes, you can use Haskell, but you should focus on elementary, general techniques and essential concepts, rather than functional programming per se.
There are a number of popular books for beginner programmers that also make it an attractive target for teaching these elementary concepts, including:
"Programming in Haskell"
"The Craft of Functional Programming"
Additionally, Haskell is already widely taught as a first language. -- but remember, the key is to focus on the core concepts as illustrated in Haskell, not to teach the large, rich language that is Haskell itself.
I'll go against the popular opinion and say that Haskell is NOT a good first programming language for the typical first-time programmer. I don't think it is as approachable for a raw beginner as imperative languages like Ruby.
The reason for this, is that people do not think about the world in a functional manner. When they see a car driving down the street, they see the same car, with ever-changing mutable state. They don't see a series of slightly different immutable cars.
If you check out other SO questions, you'll see that Haskell is pretty much never mentioned as a good choice for a beginner.
However, if you are a mathematician, or already know enough about programming to understand the value of functional programming, I think Haskell is a fine choice.
So to summarize, I think Haskell is a perfect fit for you, but not a good fit for the typical beginner.
EDIT: Thanks for the insightful comments. Owen's point that people think in a multi-paradigm manner is very true. This strengthens my belief that a multi-paradigm language like Ruby would be easier to pick up, and has the added benefit of exposing the student to both imperative and functional thinking. Haskell is decidedly not multi-paradigm.
Chuck mentioned Haskell's sophisticated type system which is another great point. While I personally prefer statically typed languages, using a dynamic language allows a beginner to ignore that piece of the puzzle until they are curious enough to find out what is going on behind the scenes. Haskell's type system, while elegant, is in your face from day 1.
Eleven reasons to use Haskell as a mathematician
I cannot write it better than that. But to summarize:
Haskell is declarative and mathematics is the ultimate declarative language, which means that code written in Haskell is remarkably similar to what you would write as a mathematical statement.
Haskell is high-level, no need to know details about caches, memory management and all the other hardware stuff. Also that means short programs which is always good.
Haskell is great for symbolic computation, algebra, logic ...
Haskell is pretty :)
To answer your question: you'll have no problem to start with a functional language as a mathematician with no programming experience. Actually it's the better choice, you won't have to repair the brain damage you would get from C/Java/whatever.
You should also check Mathematica. Some people tend to dislike it since it is a commercial closed-source product, but I think it's a pretty good environment for doing mathematics.
If you haven't had any experience at all, it will in fact be easier for you to be productive in functional programming, especially PURE functional programming. I'm an immigrant from imperative to function, I had to deal with having to forget about 80% of what I learned to be productive in Haskell.
In contrast, it's easier to switch from functional to imperative later on.
On one hand, I think Haskell is nice as a first language, but I suppose, for anyone seriously interested in programming, it should be learned in parallel with C or after C (or an assembly). C is necessary to learn what's happening under the hood, what are the costs of doing this and that, and finally appreciate the usefulness of higher level of abstraction and automatic resource management. I think when being exposed to both C (as a low-level imperative language) and Haskell (as a high-level functional language), most students will find Haskell both practical and expressive.
On the other hand, I think that programming is a craft. It is a practical activity, and it is important to learn the joy of creating something new, useful or interesting. So you need to get things done. And the easiest way for this is using a language which has tools for your problems, i.e. libraries for your data formats, algorithms for your kind of problems. And at this point, Python (or Ruby) may be a better choice, because Hackage still lags behind PyPI in many areas (and say, how many days you need to teach a novice to manipulate an image, or to plot charts in Haskell?).
So, my opinion is that some exposure to low-level imperative programming is necessary (to OOP, probably, not). Then you can understand the value of Haskell. But to get things done, and to quickly become productive, Python is a better choice for beginners. Haskell requires a few weeks before it becomes your tool.
I would say that it is suitable as a first language, and that having learned an imperative language first would probably only interfere with the learning process (since it requires lots of unlearning first).
As a caveat, I would add that a functional language principles would probably be best understood by someone with a mathematical background, as the concepts are abstract mathematical ones.
I know that many schools do teach it as a first functional language, but not as a first language.
Yes it is. Real World Haskell is a great way to get into it http://book.realworldhaskell.org/
I would hesitantly say "yes" except for the fact that in learning, finding someone as a mentor or tutor would be a much less daunting task if you chose a more imperative language to start programming. Might I suggest R or Python (with NumPy and SciPy) instead?
No.
It's very easy for a haskell98 program to be clearly understood. LYAH is a great tutorial for people with no experience but trying to prevent a learner from stumbling on extensions x, y z is gona be tricky. Soon they start to explore and become overwhelmed with advanced programming/mathematical concepts which are much harder to understand but need to be understood to read other's code.
If every piece of haskell was written in just haskell'98/'10 I would probably say yes though.
Without necessarily addressing the question as such, I would add: if you find haskell's persnicketiness too hard, do not be discouraged.
There are other programming languages, even functional ones, which are late bound.

Resources