10 ms·
Clojure is nice, but the idea that it is somehow built for the real world where Haskell isn't is just patent nonsense that I wish people wouldn't repeat. You do
by tikhonj 14y ago
Clojure is nice, but the idea that it is somehow built for the real world where Haskell isn't is just patent nonsense that I wish people wouldn't repeat. You do not need to understand complex math to actually use Haskell! All the important ideas can be understood and used in Haskell terms alone--you can think of them just like the ideas and jargon introduced in other languages. Except more general, more elegant and more consistent because they have a unifying underlying theory which the people who designed them in the first place do understand.
The biggest conceptual shift is to thinking functionally rather than imperatively, so it's going to be similar in both languages. The difference is that Haskell is more thorough, but the fundamental ideas are very similar.
Haskell, of course, has many of its own advantages which are mostly detailed elsewhere. I'm merely going to give you my highest-level take-away from trying Clojure: Haskell has much better facilities for abstraction. Haskell allows you to use types and data representation specific to your donation while still allowing you to take advantage of some very generic libraries. And the custom types are not actually complex, unlike what Clojure leads you to believe with its preference to using the basic built-in types: you construct your types from basically three fundamental operations: combining multiple values into one (like a tuple or struct), giving a choice of values (like a variant or disjoint/tagged union) or creating functions. That's all there is to them!
Basically, don't be afraid of Haskell, whatever the common wisdom is. As usual with these sorts of things, it's much more common than wise.
- rayiner 14y ago> Clojure is nice, but the idea that it is somehow built for the real world where Haskell isn't is just patent nonsense that I wish people wouldn't repeat. You do not need to understand complex math to actually use Haskell! In the abstract, possibly, but not in practice. You can't ignore the effect the general bent of the community has on the language and the code that is idiomatic in the language. People tend to describe Haskell code in mathematical terms, and libraries use operator overloading and the like in mathematical analogies.
- tikhonj 14y agoAll of the terminology used widely in the community can be--and almost always is--defined in terms of Haskell rather than math. You can pretend the math does not exist and treat it as language-specific jargon. You might miss out on the truly cutting-edge libraries until somebody writes a nice tutorial for them, but that would still be true even if the abstractions were not mathematical in nature. Many of the people in the community do not know much of the math beyond the terminology they learned in Haskell. That's certainly what I gathered talking to people at a local Haskell meetup and it matches my impression of many of the people online (e.g. in the mailing list or StackOverflow.
- chc 14y agoIf it is language-specific jargon, then people's problem is that Haskell has way too much jargon for them to wade through. No matter how you phrase it, to many people, any real Haskell is an impenetrable morass of esoteric abstractions. Basically, Haskell itself is pretty easy. The language is small, simple and elegant. But the libraries are massively, massively complex and do things in ways that are very often not at all intuitive if you're not familiar with the math behind them. That's what people mean when they say it's too heavily based in math. This is not to say that you can't use Haskell in the real world, but it has some attributes that make it daunting for many people. I don't think this a bad thing, either — not everything should be for everyone. Variety is the spice of life.
- pilgrim689 14y ago> But the libraries are massively, massively complex and do things in ways that are very often not at all intuitive if you're not familiar with the math behind them. I'm just a beginner Haskeller, but this seems like a pretty bold (and false) claim. I've used Parsec for writing a Scheme (while reading the book), Shelly and Shake for build and test automation, and some statistics libraries for, well, statistics. They were all intuitive to use, and there was no "impenetrable morass of esoteric abstractions". I'm not sure what you're on about. Maybe provide examples?
- chc 14y ago
- flyinRyan 14y agoThis just isn't true. Everything in Haskell is about the types and that's what you have to come to grips with if you want to use the language. Have you looked at projects like Yesod or Snap? Not a lot of math there but a hell of a lot about types.
- jamwt 14y agoYes, already having gotten "over the hump" on Haskell, the issue I have with Clojure is that I dig into it (finding it a truly appealing language, and wanting to achieve that sweet spot), but usually walk away thinking it really isn't giving me anything Haskell isn't, and is lacking many of the niceties I've come to rely on. I just have this feeling I would love it if I didn't already know my way around Haskell, but the "benefit-venn-diagram" feels like concentric circles. If there are some people out there who are well versed in both Haskell + Clojure, I'd love to hear some insight into where Clojure shines, and where you find yourself saying "Clojure is better at this!" in some distinct and meaningful way.
- saosebastiao 14y agoAs someone who is trying to learn Haskell, my best guess would be: Clojure's "hump" is like 1/1000000 the size of Haskell's "hump".
- kenko 14y agoWell, the Clojure repl is way better. Not being pervasively lazy makes it easier to reason about many things. Not strictly boxing IO in the IO monad makes it easier to debug (debug by println is still useful!). Macros are much easier to understand than Template Haskell, and since you don't have real typing you can have heterogeneous collections, or values where the type of one part depends on the value of another part, easily. Also I think it really is easier to get started with Clojure than with Haskell, even for the (very well thought out!) concurrency primitives, though obviously that doesn't matter if you're already up and running with Haskell. I use Clojure exclusively at my job, but for some things I really miss something like Haskell's type system, even though I freely admit I don't really understand the type system at its higher levels (specifically related to GADTs, existential types, type familes, etc.). Applicative functors would make some things so much nicer. and you don't have to understand dependent typing to do it, either. I know there are heterogeneous list implementations for Haskell, but I can never understand how they work.
- flyinRyan 14y ago>since you don't have real typing you can have heterogeneous collections You can have heterogeneous collections in Haskell, you just have to mean to. :) Check out the the "Obj" example here [1] [1] http://www.haskell.org/haskellwiki/Existential_types http://www.haskell.org/haskellwiki/Existential_types
- alberich 14y ago> I'm merely going to give you my highest-level take-away from trying Clojure: Then you go on the describe what you find good about haskell? That sounded weird.
- tikhonj 14y agoNo, I was trying to explain what the biggest difference I found between them when I tried Clojure. I agree that wasn't worded very clearly.
- swannodette 14y ago> Haskell has much better facilities for abstraction I've been using Clojure for about 5 years now. I've actively worked for the past two years on core.logic which has quite a few fancy abstractions (custom types, protocols, macros) that all interact quite nicely together. Now, I'm not a Haskell expert, but I do feel that some of the things I've built would be could be challenging in the Haskell context. I might very well be wrong about that. That said, I'm actively learning Haskell as there are some aspects of Haskell I find quite attractive and in particular a few papers that are relevant to my Clojure work that require an understanding of Haskell. My sense is that even should I eventually become proficient at Haskell, my appreciation for Clojure's approach to software engineering would be little diminished and likely vice versa.
- mjw 14y agoI'll have a crack at some suggestions, as a Clojure user (nice work on core.logic!) with some Haskell familiarity. For logic programming: you might find Control.Unification [1] interesting -- and of course if you don't need unification then you can go pretty far with the plain old List monad. Protocols/multimethods: Haskell typeclasses are really really powerful. Probably my favourite of all the approaches to polymorphism I've seen anywhere, although YMMV (they do lean heavily on the type system.) Macros: there is Template Haskell [2], which is pretty interesting although I can't claim to've used it myself. It doesn't quite share the simplicity of macros in a homoiconic dynamic language, but at the same time in Haskell it feels like you don't need to lean on compile-time metaprogramming as much as you do in a Lisp to achieve power. (Can't quite put my finger on why). [1] http://hackage.haskell.org/packages/archive/unification-fd/0.5.0/doc/html/Control-Unification.html http://hackage.haskell.org/packages/archive/unification-fd/0... [2] http://www.haskell.org/haskellwiki/Template_Haskell http://www.haskell.org/haskellwiki/Template_Haskell
- oggy 14y agoKiselyov et al have an interesting paper on logic programming in Haskell [1]. They introduce a backtracking monad transformer with fair disjunctions, and negation-as-failure and pruning operations. And the implementation is based on continuation, so it's more efficient than reification-based approaches such as e.g. Apfelmus's operational monad [2] [1]: http://www.cs.rutgers.edu/~ccshan/logicprog/LogicT-icfp2005.pdf http://www.cs.rutgers.edu/~ccshan/logicprog/LogicT-icfp2005.... [2]: http://apfelmus.nfshost.com/articles/operational-monad.html http://apfelmus.nfshost.com/articles/operational-monad.html
- da3da 14y agoI'm curious what advantages you think Haskell has over ML/Ocaml. I'm pretty familiar with OCaml and like it a lot, and Haskell seems to be very similar, but I haven't used it for anything substantive. What benefits, if any, does Haskell have over Ocaml, and is it worth learning if one already knows Ocaml? I know that Haskell has lazy evaluation while Ocaml doesn't, but you can simulate lazy evaluation in Ocaml.
- tikhonj 14y agoI actually also really love OCaml. It has some truly brilliant features which Haskell lacks like polymorphic variants (and structural sub-typing in general) and a top-notch module system. (Much unlike Haskell's "worst-in-class" module system.) Haskell does have a bunch of advantages though. A pretty petty one is syntax: Haskell's is simpler, prettier, more consistent and yet more flexible. They're very similar, of course, but I think Haskell gets all the little details right where OCaml often doesn't. The single biggest advantage Haskell has--more than enough to offset the module system, I think--is typeclasses. Typeclasses subsume many of the uses of modules, but can be entirely inferred. This moves many libraries from being too awkward, inconvenient and ugly to use to being a breeze. A great example is QuickCheck: it's much more pleasant to write property-based tests in Haskell because the type system can infer how to generate inputs from the types. Being able to dispatch based on return type is also very useful for basic abstractions like monads. Beyond this, you can also do neat things like recursive typeclass instances and multi-parameter typeclasses. Honestly, if I was forced to pick a single Haskell feature as the most important, I would probably choose typeclasses. They're extremely simple and a foundation for so much of Haskell's libraries and features. Most importantly, typeclasses are probably the most obvious way the type system goes from just preventing bugs to actually helping you write code and making the language more expressive, in a way that a dynamically typed language fundamentally cannot replicate. Laziness in Haskell is not really a big deal. It can make much of your code simpler, but it also makes dealing with some performance issues a bit trickier. It also tends to make all your code more modular; take a look at "Why Functional Programming Matters"[1]. I am personally a fan of having laziness by default, but I think it's ultimately a matter of philosophy. And philosophy, coincidentally, is another reason to learn Haskell: it takes the underlying ideas of functional programming further than OCaml. In Haskell, everything is functional and even the non-functional bits are defined in terms of functional programming. Many "functional" languages are actually imperative languages which support some functional programming features. OCaml is one of the few that goes beyond this, but there is really a qualitative difference when you go all the way. Once you know that everything is functional by default, you can move code around with impunity. You on longer have to worry about the order code gets evaluated in or even if it gets evaluated at all. You also worry far less about proper tail calls, which mostly compensates for having to deal with some laziness issues. Haskell also embraces the philosophy in another way: you tend to operate on functions like data even more than in OCaml. The immediately obvious example is that Haskell has a function composition operator in the Prelude. There is no reason for OCaml to not have this, but--as far as I know--it doesn't. It's an illustration of the philosophical differences between the two languages. On the same note, Haskell also tends to use a whole bunch of other higher-order abstractions like functors and applicatives. So I think the most compelling difference is ultimately fairly abstract: Haskell just has a different philosophy than OCaml. This ends up reflected in the libraries, language design and common idioms and thus in your code. I think that by itself is a very good reason to learn Haskell even if you know OCaml; and since you do, picking Haskell up will be relatively easy!
- coldtea 14y ago>Clojure is nice, but the idea that it is somehow built for the real world where Haskell isn't is just patent nonsense that I wish people wouldn't repeat. Really? Because SPJ, for one seems to agree with it.
- gphilippart 14y agoColdtea, could you provide a link where SPJ says this ? I googled it but couldn't find anything.
- cgag 14y agoI think he may be talking about this: https://www.youtube.com/watch?v=iSmkqocn0oQ https://www.youtube.com/watch?v=iSmkqocn0oQ
- coldtea 14y agoYes. Plus the cheeky "avoid success at all costs" remarks etc. Of course he doesn't mean it's not usable (or used already) in the real world at all. Just that it's not in the perfect practical form that a real world language would have.
- pron 14y agoEven if Haskell could somehow be proven to be "the better language" (whatever that means), Clojure is still extremely elegant, simple and beautiful, and it has one huge advantage: it runs on the JVM, so it automatically harnesses the vast JVM ecosystem, as well as all of its (unmatched, IMO) monitoring, profiling and runtime-instrumentation tools (+ dynamic class-loading and hot code replacement).
- michaelsbradley 14y agoTried Frege? https://github.com/Frege/frege https://github.com/Frege/frege "Frege is a non-strict, pure functional programming language in the spirit of Haskell ... Frege programs are compiled to Java and run in a JVM. Existing Java Classes and Methods can be used seamlessly from Frege."
- technomancy 14y agoIndeed, I think when most people say "suitable for real world projects" they mean "I can get away with using this at work because it's just a jar".
- djhworld 14y agoI think Haskell is great but it's weak in libraries. This is where Clojure has a slight advantage because you can tap into the Java ecosystem for stuff that isn't currently in the Clojure world. Database libraries are a good example of this, database support in Haskell is still pretty flaky and cumbersome to setup in comparison to JDBC.
- berlinbrown 14y agoI think you can use both. As Clojure is more dynamic in nature where Scala/Haskell are good compiled static compliments. Large projects, I would go with Scala/Haskell and for front-end systems, I would use clojure. Why do it this way? With clojure, you can easily modify data or small pieces of logic. Simply edit the script without the recompile. With the scala/haskell api or library, you probably need something that changes less frequently. That backend system may act as a core piece of your library. ... And if you don't like that. You can do Python and Java/C# which can give you the same effect.
- jwr 14y agoA meta-comment: I find it amazing that we are arguing whether Clojure or Haskell is better suited for real-world applications. Discussions like this one convince me that we have advanced our programming techniques over the last decade or so. After all, we could be arguing about semicolons, the GOTO statement, or other similarly important issues. It's a nice feeling.
- altcognito 14y agoSure, arguing that a functional language is the solution to our problems hasn't been done since oooo.... LISP? We have come so far.
- AimHere 14y agoThe arguing here is which functional language is the solution, not arguing that a functional one is!
- weavejester 14y ago"And the custom types are not actually complex, unlike what Clojure leads you to believe with its preference to using the basic built-in types" Custom data types are not always complex, but efficient and useful data types often are. Clojure's data structures have very good performance for immutable data structures. Clojure's maps, for instance, have what effectively amounts to a O(1) lookup, while Haskell's Data.Map is a size balanced binary tree with only O(log n) performance.
- dons 14y ago> effectively amounts to a O(1) lookup So O(log n) then. We obey gravity around these parts. I presume you are referring to HAMT-like structures ,such as found in http://hackage.haskell.org/packages/archive/unordered-containers/0.2.3.0/doc/html/Data-HashMap-Strict.html http://hackage.haskell.org/packages/archive/unordered-contai... which are by no means unique to Clojure. Besides simply having the data type, you still need a good allocator and GC optimized for immutable data, which is where GHC stands alone - http://benchmarksgame.alioth.debian.org/u32q/benchmark.php?test=all&lang=clojure&lang2=ghc http://benchmarksgame.alioth.debian.org/u32q/benchmark.php?t...
- weavejester 14y ago> So O(log n) then. We obey gravity around these parts. Which is of no practical difference to O(1) if log n is always very small. > I presume you are referring to HAMT-like structures... which are by no means unique to Clojure. Of course they're not. My point was that it is not trivial to derive a efficient and useful data structure like a HAMT from Haskell's type system. The data structures in a library like unordered-containers are in practise just as opaque to the developer as the core data structures in Clojure.
- dons 14y ago> as opaque to the developer http://hackage.haskell.org/packages/archive/unordered-containers/0.2.3.0/doc/html/src/Data-HashMap-Base.html#HashMap http://hackage.haskell.org/packages/archive/unordered-contai... This highly optimized data type is defined in 6 lines, easily accessible from the docs.
- sedachv 14y ago+1. People get themselves worked up about words like "monads" and "algebraic data types," but using those things is not difficult, and the amount of guarantees they give you about your code is so far beyond anything else out there that IMO it's not worth doing functional programming unless you have a proper type system together with monads.
- jes5199 14y agoHaskell got some sharp edges which make me hesitant to use it. I once had a Haskell program that had a serious space leak that would cause it to exhaust ram and crash. The culprit? Adding "+1" to a counter repeatedly and then never evaluating the counter. It took a very smart programmer (who happens to have a PhD in math) six hours of debugging to find it. Also I've never seen Haskell's FFI work - it's just too much of a pain. Clojure's Java integration works right out of the box.
- homeomorphic 14y ago> Also I've never seen Haskell's FFI work - it's just too much of a pain. For what it's worth, I've found Haskell's FFI very pleasant for interfacing with C (and the reverse looks just the same, but I haven't tried). You then interface with any othet language through C, since most can FFI through C anyway. I think it's a very reasonable solution!
- dons 14y ago> six hours of debugging I guess this just shows that Math PhDs don't know how to use the fine profiler: http://stackoverflow.com/questions/15046547/stack-overflow-in-monoidal-fold-over-large-list/15046901#15046901 http://stackoverflow.com/questions/15046547/stack-overflow-i... Which would have saved about 5hrs 50mins...
- dschiptsov 14y agoThis is just a propaganda - repetitive reciting of slogans made of long words.) It is, of course, difficult to argue with zealots, but I will try nevertheless.) The cost of what is called "advanced type system" is inability to put an elements of different types in the same list or tuple or whatever. It is not just a feature, it is a limitation. In some cases, when you, for example, dealing only with numbers, say, positive integers, it is OK, but what then the real advantage of such type checking? On the other case, the concept of a pointer which all those "packers" trying to throw away is very mind-natural. When we have a box we could put anything in it, as long as it fits. Imagine what a disaster it would be when you moving from one flat to another but must pack stuff only into special kind of boxes. This one is only for such kind of shoes, this is only for spoons, that for forks. So, with a pointer we could "pick up" everything, and then decide what it is and where it goes. Another mind friendly concept is using symbols and synonyms to refer to thing - s symbolic pointers. It is how our minds work. Those who are able of thinking in more than one language know that we could refer to it using different words, but "inner representation" is one and the same. These two simple ideas - using pointers (references) and have data ("representation") to define itself (type-tagging is another great idea - it is labeling) gives you a very natural way of programming. It is a mix of so-called "data-directed" and "declarative" and, as long as you describe a transformation rules instead of imperative step-by-step processes, "functional" styles. Of course, the code will look in a certain way - there will be lots of case-analysis, like unpacking things form a big box - oh, this is a book - it goes to a shelf, it is a computer speakers, it goes on the table, etc. But that's OK, it is natural. The claims that "packing" is the best strategy is, of course, nonsense. Trying to mimic natural processes in our mind (as lousy as we could do it) is, in my opinion, has some sense. There are some good ideas behind each language and not so good. Symbolic computation, pattern matching, data-description (what s-expression, or yaml is) are good ones. Static typing, describing "properties" instead of "behavior" - not so.) Also it is good to remember that we're programming computers, not VMs. There is something called "machine representation" which is, well, just bits. It doesn't mean to swing into another extreme and program in assembly, but it is advisable to stay close to hardware, especially when it is not that difficult. Everything is built from pointers, you like it or not.) The idea to throw them away is insane, the idea (a discipline) of not doing math on them is much better. The idea of avoiding over-writing is a great one, it is good even for paper and pencil - everything become a mess very quickly, but avoiding all mutation is, of course, madness. So, finding the balance is the difficult task, and it is certainly not Haskell. Classic Lisps came close, but it requires some skill to appreciate the beauty.) So, the most popular languages are the ugliest ones.