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.

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site, so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. More info: help center.

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.
If this question can be reworded to fit the rules in the help center, please edit the question.

34

2.5 months is not enough time to learn any language in depth, sorry to burst your bubble.
–
Woot4MooSep 22 '10 at 15:20

20

That's certainly true. I didn't mean to imply that I'd "learned" Haskell, whatever that means. I meant that I feel comfortable using the language. I clearly won't "stop learning" it.
–
danportinSep 22 '10 at 15:25

10

@Michael: Coding for correctness instead of efficiency is something I'd love to see more of...
–
Deniz DoganSep 22 '10 at 15:33

24

@Woot4Moo: 2.5 months is plenty of time to get "comfortable" with a language, though. Doubly so if he's familiar with formal logic and working with abstract concepts from his philosophy background. Not having to unlearn habits from other languages would also help in this case.
–
C. A. McCannSep 22 '10 at 15:44

8

@gnovice: It has been asked a lot of times, certainly. But this is the first time I come across somebody who has done his first serious programming experience with Haskell. It's like the arrow of time has been inverted or something.
–
Muhammad AlkarouriSep 22 '10 at 17:42

17 Answers
17

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.

What would be the annoying limitations of F# in your opinion? As someone learning F# in their spare time, I'm curious to know.
–
LucasSep 22 '10 at 21:14

7

@Lucas: The big one vs. bare-bones Haskell is lack of higher-kinded polymorphism and type classes. Beyond that, quite a few GHC-specific extensions are pretty nice. None of it's a fatal flaw by any means, but after getting used to Haskell it just feels kinda clumsy not having that stuff. Imagine going from modern C# back to using C# 1.x...
–
C. A. McCannSep 22 '10 at 21:51

@HyneK: This Qi 2 language at first glance seems very interesting and more flexible than either Coq or Adga. It seems though the author has decided to call it quits. Is there any movement to continue working on this language? I wouldnt want to learn something that is already half dead.
–
AlexOct 15 '10 at 8:20

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.

Heh, from a Haskell perspective, type hinting or optional static typing don't really look all that different from completely dynamic typing. It's a very different mindset. That said, Lisp-y languages are all kinds of fun and are something I think every programmer should spend at least some time learning.
–
C. A. McCannSep 22 '10 at 17:53

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.

As you state an interest in a strongly typed language, I'd recommend lambdaProlog, a typed higher-order logic programming language. One compiled implementation is Teyjus - code.google.com/p/teyjus (disclosure: I worked on Teyjus).
–
Zach SnowOct 7 '10 at 15:03

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.

It's also worth noting that if, as a philosophy major, he has a lot of experience with formal logic, Curry-Howard-style proof assistants may very well be less baffling to him than they would be to most veteran programmers!
–
C. A. McCannSep 22 '10 at 16:34

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.

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.

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.

+1 also see my comment on larsmans's answer. But be careful to advertise Python as rather functional. For example, generator expressions are usually preferred over map, filter, etc. But still, generators and generator expressions will feel familiar to someone who knows lazy evaluation and the said functions.
–
delnanSep 22 '10 at 15:45

16

Really? I think Python mostly seems particularly functional to people who haven't done much functional programming. I've used both Python and Haskell a fair amount, and while Python is a nice language, and certainly has borrowed a few things from functional languages, it's still 99% imperative.
–
C. A. McCannSep 22 '10 at 16:41

@camccann You're right--my perspective is different, which is why I'm just offering this as an interesting alternative. As someone who learned imperative programming first, I appreciate that Python lets me use functional techniques where they are appropriate and avoid them where something else makes sense. I'm not making the case that it "is" functional--only that it makes a good compromise.
–
Tim YatesSep 22 '10 at 18:19

The habits learned from Haskell can make you a much better Python programmer than others who learnt it as first language.
–
u0b34a0f6aeNov 12 '10 at 9:37

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.

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).

+1 for first paragraph, exactly what I thought when I read the question. For the sake of learning new things, I would suggest a modern imperative language, like Python - especially since it's not what the OP's used to (dynamic typing, iterators everywhere, etc). It also has very cool advanced concepts like metaclasses or generators (which are strikingly similar to lazy lists)/generator expressions (which serve as a generalization of list comprehensions + generators). Also, dict and set comprehensions rule.
–
delnanSep 22 '10 at 15:35

3

@delnan: Haskell has list comprehensions as well and generators/iterators can easily be expressed in Haskell using Haskell's standard list type. So the biggest differences between the two languages would in my opinion be object-oriented programming and (most often) impure data structures such as dictionaries.
–
Deniz DoganSep 22 '10 at 15:45

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.

Asking a Haskeller to move to Java is like asking Bill Gates to move to slums. :-/
–
missingfaktorSep 22 '10 at 20:26

1

+1 For suggesting something that will definitely get you downvoted. Java and C# have nice ecosystems and are both very recommended for serious work. As a definite plus you can leverage your knowledge of Haskell (, Java and C#) when using Clojure on the JVM or F# on the CLR.
–
ponzaoSep 22 '10 at 20:53

6

@ponzao: Urgh, no, suggesting that someone go from Haskell to Java or C# is just horrible and cruel. Scala, F#, and Clojure are much nicer languages with all the same benefits that come from running on the JVM/CLR.
–
C. A. McCannSep 22 '10 at 21:06

5

For an analytic philosophy major Java or C# are a waste of time.
–
MaD70Oct 8 '10 at 0:09

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: