My somewhat neglected library Clearley (https://github.com/mthvedt/clearley) uses a macro system, that lets you write parsers that look a little like pattern-matching functions. To do this, you need to be able to introspect, bind and lookup symbols, and data structures containing symbols, at compile time. You can't do this in Haskell. Template Haskell doesn't help, since IIRC it doesn't support looking up symbols in the same file.
With Clojure, If you understand the JVM type system and performance, you can also write high performance DSLs using Clojure macros. https://github.com/clojure/core.logic allegedly is a project along these lines, but I haven't looked too much into it. It heavily uses Clojure protocols (which map to Java interfaces) for performance. I had been working on a code generator for Clearley, which sits neglected on my hard drive, but is able to perform just a little slower than unoptimized hand-written parsers. Since in Clojure compile/runtime separation is optional and off by default, you can use Clojure to generate Clojure code, making life a lot easier.
It's so completely trivial to generate examples of things that Lisp macros can do that Haskell's laziness cannot achieve, it muddies the subject. Try implementing lambda-case or anything written in template-haskell in laziness: you cannot. That's where Lisp macros shine. :-)
As Lisp macros are compile time metaprogramming, wouldn't the answer to this depend on whether Template Haskell is considered part of Haskell or just a compiler extension?
Actually they're macro expansion time meta programming. Common Lisp also has compiler macros, which are slightly different (in addition to regular macros).
Lisps generally run in an image, meaning you have full access to he full state of the program including the compiler/macro expander/etc, which you can run at runtime.
So what about a program that reads a protocol off the wire, expands/compiles it to x86_64 assembly, and communicates over the wire with it (all in the same process and without calling any external compiler).
Or maybe a program that collects runtime performance statistics and uses some stochastic method to improve the 'hot' pieces of code.
I use Clojure for almost everything now, but I must say Haskell looks interesting. My issue is that Clojure is thriving right now, and Haskell has been around longer than I've been and the world sees it as some arcane science. Is it really worth investing my time to learn it if it's really not being used that much?
It seems fair to say that Lisp was also considered arcane for a number of years, although it is now (somewhat) thriving in the form of Clojure. It's a tough question to answer, but I think you're really asking whether it's better to take a chance of being any sort of early adopter, or wait until it's generally accepted.
Even though these languages have been around for decades, they are just recently being spliced into the mainstream via lambdas, immutability, etc. So I could easily see Haskell make a comeback.
I think you might be overestimating the actual usage of Clojure. It's still very much a niche language.
Everything I've observed suggests that Scala has a far greater rate of adoption than Clojure, and Scala's usage is still basically irrelevant compared to that of the major entrenched languages. I'd put the adoption of Haskell closer to that of Scala than I would to Clojure.
As a long-time Lisper in AI, Haskell does look intriguing, but I'm more worried about what I would lose. In particular, I'm curious about how DSLs fare in Haskell. I can write first-order logic sentences in Lisp, and they look and behave just like any other Lisp code. I can use evolutionary programming to generate new code on the fly, and send it to the compiler. And I can get really down to the metal if I ever need C-level performance.
I've never learned Lisp, but my motivation for learning Haskell (after briefly toying around with it) was to create a DSL. Specifically, I was designing a DSL with the intention of implementing it in python, when I realized that my DSL seemed a lot like a monad in do notation. Implementing it didn't fail to dissapoint in just how easy it was. Having said that, a DSL implemented as a monad does not behave like any other haskell code, in that it is a monad, and only looks like a DSL when used in do notation.
As a Lisper who moved to Haskell, you will find Haskell lacking without template-haskell. With TemplateHaskell turned on, you can do the equivalent of quasi-quotes and reader macros:
But regular, syntax-extending macros aren't possible. E.g. you can't write AIF, there is only quasiquotation. But if you're just worried about DSLs, then that is indeed possible. There's a culture of avoiding template-haskell in favour of using combinators, so you will sometimes have to stomach ugly DSLs with awful operators and silly names. On the other hand lazy functions are like compiler macros, so they compose better than Lisp macros, which generally compose horribly.
- The syntax is clean and extensible. (Function application is `f(x)` in C, `(f x)` in Lisp, and `f x` in Haskell.)
- The core language is small, with a suprising amount of functionality implemented as library functions. (Not surprising to a Lisp programmer, though.)
- You can define your own infix operators, specify their precedence, and their fixity. (Left, like most mathematical operators, or right, like the exponentiation operator).
- Because of Haskell's lazy evaluation, there is no distinction between special and non-special forms, so you don't need macros to build up syntactic sugar for your DSL. (Special forms, such as the C short-circuiting operators `&&` and `||`, only evaluate as much as is necessary, which is what Haskell does across the board.)
- But if you really want macros or quasi-quotation, they're part of the language. (Macros are named Template Haskell.)
- There is also built-in syntactic sugar which can be re-used for your own instances of common program patterns, such as monadic do-notation, monadic comprehensions, and arrows.
There are many examples of Haskell DSLs online. A particularly amusing one is Lennart Augustsson's embedding of BASIC in Haskell, proving beyond all doubt that Haskell is in fact an imperative language, and all this talk about purity is poppycock. [1] [2]
Haskell is also great for performance. GHC 7.8.2 is now ready to use, with the Mio high-performance multicore IO manager merged in. [3] The composable nature of Haskell also lends itself to surprisingly powerful optimisations. [4]
Now, generating code at runtime and integrating it (interpreted, or even compiled) into the running image is definitely a strength of Lisp, and other under-appreciated artefacts of a future past, such as Smalltalk. I do not know how Haskell fares in this area, but I would like to find out.
Except macros are great for more than just lazy evaluation. For instance, completely altering syntax to make your app make a lot more sense and remove any amount of boilerplate.
As far as parallelism, sure Haskell can give that for free. The cost is you have to be pure about everything, which just seems obnoxious to me...especially when you don't necessarily care about parallelism or performance.
With lisp, I can use macros to make parallelism just as natural as programming regular lisp. Yes, I have to be explicit about when I'm being parallel and when I'm not. But that doesn't seem like such a big deal to me, and sometimes you want explicit control over your threads.
As far as community, I have no doubts the Haskell community is great. But so is the lisp community. There are a lot of bright people who jump at any chance to help out others, and in the past 5 years the CL implementations and community-built libraries have been making leaps and bounds.
This isn't to say Haskell isn't a great choice for many, many applications and requirements. But it's not a replacement for lisp, just as lisp isn't a replacement for Haskell. They are two different beasts that are great at different things.
>Except macros are great for more than just lazy evaluation.
Haskellers agree, that's why we have Template Haskell. We use it for all sorts of things, like automatically implementing typeclasses (interface'ish) at compile-time.
> parallelism, sure Haskell can give that for free
> So you can know what you're talking about next time, my recommended guide for Haskell:
I like your guide, but is this really necessary? This isn't the first time you've been aggressively hostile to people expressing a preference for Lisp over Haskell, either.
It was imperfectly stated and with unconstructive tone. I allowed my irritation at statements made about Haskell by someone that hadn't used it get to me. That's my fault.
Would be nice if the culture could shift a notch or two towards, "know nothing -> say nothing" though.
It's a shame to see that comment getting modded down. It's absolutely valid and correct. The three examples given in that other comment are pretty much unknown. xmonad might be a slightly better example, but it's still pretty much unknown, too.
While Haskell has seen some usage, of course, we really haven't seen any major and widely-used non-compiler software developed using it. It's perfectly legitimate to point this out, and using very obscure counterexamples doesn't change this reality.
The measure of a programming language isn't whether it becomes "mainstream." It's whether it can be used to make useful programs. Others have already provided many examples of useful Haskell programs (none of which are "yet another compiler"), so I'm not sure what else needs to be said.
By the way, I don't know Haskell, but I am writing this comment from XMonad. :)
To put a more positive spin on this, I'd be interested if someone could point to a practical, in use, open source project written in Haskell that I could learn from please?
All the tutorials and theory make sense, but making the jump to what I can do with other languages still seems a big one.
I'm a relative newbie when it comes to Haskell; I've found it's best to just get stuck in - pick a project and just go for it. Especially if you're doing real-world stuff, because you'll just get sick to your back teeth of yet another fibonacci tutorial. Once you get stuck-in you'll find yourself on the Hackage docs site a lot, click on the Source link on the top right of every page, you'll find gold in there.
A real world thing I did this week (which unfortunately is proprietary so I can't share), was a distributed configuration system for our cluster. It uses the RabbitMQ library[1][2] and Acid-state library[3] to have a per-node config-DB and uses RabbitMQ's guarantees for delivery of updates to the nodes. Messages are serialised using Aeson[4], the Haskell JSON library. I implemented a vector-clock versioning system on top of the Acid-state store to allow the clients to do conflict resolution. It really was a joy to write (around 350 lines of code). The C# client less so, 1000s of lines of boilerplate.
I think there's something really impressive about haskell; I tend to have significantly more trust in the code I write because mostly I know the edge cases don't exist. 9 times out of 10 if your code compiles it will work. Although be prepared for the compiler to hate you when you first start. The beatings are worth it though.
Pandoc, which I linked above fits into your question nicely. And because you specifically asked about something to learn from: there are some well made Youtube videos which explain some of the code in pandoc and xmonad: https://www.youtube.com/watch?v=FEFETKhhq8w
I think that's backing up the point he's making, though. When considering the big picture, tiling window managers are quite minor and relatively infrequently used.
Having a small amount of influence within a rather obscure field ends up translating to basically no importance in practice.
There are many examples of very large and critical software systems implemented in languages like C, C++, Java, C#, Perl, Python, Ruby, and others. We just don't see anything like this when it comes to Haskell, however. The examples that do exist are quite minor in reality, and this will naturally make some people skeptical about Haskell's practicality.
That kind of stuff just takes a bit of time. It's kind of irrelevant to the language itself. Python and Ruby didn't hit the mainstream until the 2000's, despite being invented in the 90's. C# and Java both have huge company backing, and C and C++ have had traction since the 80's and earlier. And we all know sysadmins love Perl. Haskell's popularity is only a recent thing. It only kicked off with a few proper books in the past few years.
I wouldn't exactly call Haskell "popular". It isn't as obscure as some programming languages, but realistically, it sees comparatively little use in practice.
And Haskell predates Python, Ruby, JavaScript, Java and C#. It has had a very long time to become more widely used, yet we just haven't seen this happen. It's not like people don't know about it; many students, academics and practitioners have been exposed to it for years now, and it does get a fair amount of hype for a language that has experienced limited use in practice.
I just don't think it offers enough benefit for the cost involved with learning and using it. If the balance were better, we'd see it being used. But that isn't the case, so it sees minimal usage.
Check out /r/unixporn. There are some excellent setups in there. I think the lack of a standout tiling window manager might be the result of the quantity of excellent WMs in existence. Regardless, if you've never had an experience using a tiling window manager, I would highly recommend it. Once you get past a certain threshold, your productivity skyrockets!
Sure, my Symbolics Lisp Machine had a tiling window manager 30 years ago. Today I could use Stumpwm, written in Common Lisp. It's just that I don't use X that much...
He's merely pointing out the very real fact that Haskell's adoption is quite limited, and the fact that there really isn't much truly critical software written using it, despite the hype surrounding it and its age.
I'd say it has made more of an impact by influencing other, more pragmatic languages than it has by software written using it.
How did you go from "never going to go mainstream" to "not worth learning"?
First of all, you are right. Haskell is never going to become as common as C or Java, and I don't think anybody is claiming that it will. It is a language that is designed around theoretical concerns rather than being pragmatic. But that is exactly what makes it so valuable to learn.
Realistically, I don't think that knowing Haskell really would benefit most programmers, especially those working on typical, everyday software systems.
There are some relatively niche situations where it might be a good choice, but those are few and far between.
We've seen the most useful and practical features offered by Haskell make their way into other more mainstream languages over the years. The more theoretical features haven't made this transition because they really aren't all that practical.
At this point, most programmers would be better off learning more about security, cryptography, databases, networking and other everyday topics than they would be by learning about the more theoretical functionality offered by Haskell.
Realistically, I don't think that knowing Haskell really would benefit most programmers, especially those working on typical, everyday software systems.
Just curious. How much Haskell/FP experience do you have?
A fair amount. I used ML and Haskell in the 1990s in an academic setting, and have since used Haskell, Erlang, and Scala at various times while in industry. And I've tried out a number of other functional languages out of interest, as well.
Functional programming does offer some benefits, in some cases. I'm not suggesting that it doesn't. And while I don't think it'd be harmful to know Haskell, I'm not convinced that the benefit it would bring is necessarily worth the effort involved, especially for programmers who are already busy with work and other commitments.
Just because not a lot of programmers understand the language yet doesn't mean that programmers in the future can't learn it and take advantage of it. I hope they do, because just by programming in haskell, you automatically rule out entire classes of bugs.
[0] https://news.ycombinator.com/item?id=516208
[1] https://news.ycombinator.com/user?id=ntoshev
[2] https://news.ycombinator.com/item?id=516038