Haskell is most closely related to the ML family of languages. This includes things like OCaml, of course, but also F# on the .NET platform. These languages share with Haskell the foundation of the type system and how data is used--algebraic data types, pattern matching, type inference, etc. They can differ substantially from Haskell on other points, of course--most MLs are strict and impure, to start with, and the popularity of Haskell as a vehicle for research in type systems and language design means that most ML-style languages tend to have less powerful (but potentially easier to understand) type systems. It's probably safe to say that while you may miss some things about Haskell, particularly at first, most Haskell programmers would probably feel comfortably at home in an ML pretty quickly, at a basic getting-things-done level. If you want a language with the same overall structure as Haskell, an ML is your best bet.
The functional side of Scala draws heavily from the ML tradition, as well, and also pulls in some advanced type system features familiar from Haskell, as well as a more standard OOP system integrated with the above. While OO in ML-style languages tends to be approached as more of a "model OO with basic functional tools" Scala lives and breathes Java-style OO. This has benefits for Java interop, as you might imagine, and presents more familiar working environment for OO programmers. However, coming from a Haskell background, you're more likely to be annoyed by ways that blending things together in Scala makes functional idioms clumsier, and find most Java APIs to be badly designed and needlessly difficult to use. So if you want something with a sophisticated type system that permits direct translations of many things in Haskell (with some extra syntactic overhead) and don't mind compromising on functional style, you might enjoy Scala.
Finally, while it may seem odd to consider, Clojure actually has a lot of things in common with Haskell at a more philosophical level. Most of what you'll find in Clojure's approach to state and values vs. identities is very close in spirit to what Haskell formalizes through the type system. Correspondingly, Clojure emphasizes Java interop to a smaller degree and doesn't worry as much about dragging in OOP, so in some ways Clojure's approach to functional programming itself may be closest to what you're already familiar with. I think it's telling in this regard that, to the best of my knowledge, Clojure is the only language besides Haskell that has an implementation of STM that's simple, effective, and just works. On the other hand, Clojure comes from the Lisp tradition and thus lacks the static type system and emphasis on algebraic data types and pattern matching found in ML-influenced languages. And of course it's a Lisp, which is itself a negative to some people (though I really don't know why).
Speaking for myself, with the disclaimer that my first experience with functional programming was in Scheme, I'd probably lean toward Clojure, with OCaml a likely second choice.
Notwithstanding any specific ideas on the part of language designers, it bears mentioning that authors and stewards of programming languages are, in the end, pushing a product. So, I might ask why I'd want a camera-phone when my plain phone is a better phone and my camera a better camera, but that isn't going to stop manufacturers of both devices from trying to broaden their product's offering to attract new customers.
Once you look at it from that perspective, then notions of preserving the integrity of the original language become a matter of degrees and tradeoffs. If I'm the author of OOP language AwesomeCode and I see people starting to get interested in new functional language FCode, do I tell my users "sorry, but this is an OOP language only" and risk them going to C# instead to get at its lambas, or do I cave and grudgingly include some of FCode's functionality?
Best Answer
I realize I'm coming late to the party, but you've had two theoretical answers here, and I wanted to provide a practical alternative to chew over. I'm coming at this as a relative Haskell noob who nonetheless has been recently force-marched through the subject of Arrows for a project I'm currently working on.
First, you can productively solve most problems in Haskell without reaching for Arrows. Some notable Haskellers genuinely do not like and do not use them (see here, here, and here for more on this). So if you're saying to yourself "Hey, I don't need these," understand that you may genuinely be correct.
What I found most frustrating about Arrows when I first learned them was how the tutorials on the subject inevitably reached for the analogy of circuitry. If you look at Arrow code -- the sugared variety, at least -- it resembles nothing so much as a Hardware Defnition Language. Your inputs line up on the right, your outputs on the left, and if you fail to wire them all up properly they simply fail to fire. I thought to myself: Really? Is this where we've ended up? Have we created a language so completely high-level that it once again consists of copper wires and solder?
The correct answer to this, as far as I've been able to determine, is: Actually, yes. The killer use case right now for Arrows is FRP (think Yampa, games, music, and reactive systems in general). The problem facing FRP is largely the same problem facing all other synchronous messaging systems: how to wire a continuous stream of inputs into a continuous stream of outputs without dropping relevant information or springing leaks. You can model the streams as lists -- several recent FRP systems use this approach -- but when you have a lot of inputs lists become almost impossible to manage. You need to insulate yourself from the current.
What Arrows allow in FRP systems is the composition of functions into a network while at the same time entirely abstracting away any reference at all to the underlying values being passed by those functions. If you're new to FP, this can be confusing at first, and then mind-blowing when you've absorbed the implications of it. You've only recently absorbed the idea that functions can be abstracted, and how to understand a list like
[(*), (+), (-)]
as being of type[(a -> a -> a)]
. With Arrows, you can push the abstraction one layer further.This additional ability to abstract carries with it its own dangers. For one thing, it can push GHC into corner cases where it doesn't know what to make of your type assumptions. You'll have to be prepared to think at the type level -- this is an excellent opportunity to learn about kinds and RankNTypes and other such topics.
There are also a number of examples of what I'd call "Stupid Arrow Stunts" where the coder reaches for some Arrow combinator just because he or she wants to show off a neat trick with tuples. (Here's my own trivial contribution to the madness.) Feel free to ignore such hot-dogging when you come across it in the wild.
NOTE: As I mentioned above, I'm a relative noob. If I've promulgated any misconceptions above, please feel free to correct me.