Lennart Augustsson
augustss.blogspot.com · Personal blog · on HN since 2009
Lennart Augustsson, a Haskell compiler developer, writes about Haskell, lazy evaluation, LLVM code generation, and implementing dependently typed languages.
What HN saysHN links his posts for arguments about laziness and a dependent types tutorial one commenter praises as brilliant, though another calls his quicksort example a bait-and-switch.
42HN people shared it
36linked it in comments
8stories submitted
105story points
11 months agolast shared
2009people per year2026
Most-shared posts
- 1More points for laziness11 people · 8 points · first shared 2011 · discussion on HN
- 2More basic not that anybody should care5 people · first shared 2012
- 3Quicksort in haskell quicksort is4 people · first shared 2011
- 4More points for lazy evaluation in4 people · first shared 2015
- 5Using LLVM to generate fast machine code from Haskell3 people · 9 points · first shared 2009 · discussion on HN
- 6Simpler, Easier (2007)2 people · 10 points · first shared 2015 · 3 comments on HN
- 7Haskell for Basic (circa 1978) fans2 people · 10 points · first shared 2009 · discussion on HN
- 8Programming in c ummm haskell heres2 people · first shared 2013
- 9BASIC as a Haskell DSL (2009)1 people · 58 points · first shared 2014 · 12 comments on HN
- 10Ugly Memoization1 people · 6 points · first shared 2011 · discussion on HN
- 11It's time for some more Haskell opinions1 people · 4 points · first shared 2024 · discussion on HN
- 12BASIC1 people · first shared 2017
- 13Simpler easier in recent paper simply1 people · first shared 2019
- 14Quicksort in haskell quicksort is1 people · first shared 2013
- 15Impredicative polymorphism use case in1 people · first shared 2012
What HN people wrote when they linked it
tromp · 2022-02-21
Lennart Augustsson once wrote the least-Haskell Haskell program, amazingly without the help of a preprocessor:
https://augustss.blogspot.com/2009/02/regression-they-say-that-as-you-…
And to answer the question in the top comment:
https://hackage.haskell.org/package/BASIC-0.1.5.0/docs/Language-BASIC.…
topmonk · 2019-11-26
If you know Haskell,
or are willing to learn, this is a brilliant explanation with code (you build a dependently typed language as you go). It ramps you up very fast yet each step is accessible. This alone really caused me to get bit by the dependent type bug.
https://augustss.blogspot.com/2007/10/simpler-easier-in-recent-paper-s…
Here is the example code from this post
https://github.com/scott-fleischman/simpler-easier?files=1
willtim · 2019-05-23
It's easy to forgot the benefits of laziness: http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-i…
Laziness is a good default for declarative programming. Nix from NixOS is an example of a recent lazy language and benefits greatly from it.
Even in strict languages, lazy behaviour is often added, for example iterators and streams. Mixing effects and mutation with such constructs is also problematic.
loqi · 2014-12-04
When is quicksort not quicksort? When it's not in-place: http://augustss.blogspot.com/2007/08/quicksort-in-haskell-quicksort-is…
I love me some Haskell, but this particular example is kind of a bait-and-switch.
chongli · 2014-05-07
I wanted to avoid getting into a discussion about the merits of Haskell vs other languages. I was merely making a statement about what I perceive is the common practice of Haskell programmers. Do I believe that Haskell as a language provides features which allow for greater modularity, reusability, composability and generality than most other languages? Yes. However, to explain it all in great detail would take far too long. Besides that, others have already laid much of the groundwork for explaining these advantages in a much better format than I can muster here. Here's one simple example (which happens to describe the advantages of laziness):
http://augustss.blogspot.ca/2011/05/more-points-for-lazy-evaluation-in…
sfvisser · 2013-08-26
> ...I don't see myself using much Haskell precisely because its tools for modularity seem limited.
> Dynamic languages are naturally more modular
Why is that? I'm pretty convinced pure and especially lazy languages allow for great modularity.
See http://augustss.blogspot.nl/2011/05/more-points-for-lazy-evaluation-in… for an interesting view on this.
nandemo · 2013-07-01
That's right. That Haskell faux-quicksort uses a lot of extra space for the temporary lists.
Here's a Haskell version of the "real" quicksort, though it isn't nearly easy a read as the faux-quicksort:
http://augustss.blogspot.jp/2007/08/quicksort-in-haskell-quicksort-is.…
For what is worth, the standard Haskell sort is a variant of merge sort.
http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/D…
Peaker · 2012-01-26
Haskell makes some array access operations cumbersome due to syntactic issues with the library's API.
It is not inherent that Haskell's quickSort is harder than quickSort in C.
Take a look at Augustusson's imperative language DSLs in Haskell:
http://augustss.blogspot.com/2011/07/impredicative-polymorphism-use-ca…
Haskell is so versatile at this, augustusson managed to implement an old BASIC DSL!
http://augustss.blogspot.com/2009/02/more-basic-not-that-anybody-shoul…
I think Haskell can be a great vehicle for all our current day imperative programming needs (even if due to some library issues it's not quite as nice for all tasks yet).
yoneda · 2021-02-27
This is a great writeup, and I just want to offer a counterpoint regarding the eager vs. lazy trade-offs.
I found this article really helpful for explaining why laziness is important: http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-i…
In particular, scroll down to the "Reuse" section. Lazy evaluation enables you to compose functions to build new functions with the right performance characteristics (constant factors aside), as in:
any :: (a -> Bool) -> [a] -> Bool
any p = or . map p
In an eager language, predicate `p` would have to be evaluated on every element in the list, even if the predicate is already satisfied after the first element. So instead you'd have to write this function in an ad hoc way with explicit recursion/looping, without being able to reuse the more primitive functions.
Of course, in an impure language, laziness can't be the default because you wouldn't be able to reason about when your side effects occur. But in my mind that's an argument for purity rather than an argument for eagerness.
BTW, comparing "strict" vs. "lazy" is a category error. The proper comparison would be either "strict" vs. "non-strict" or "eager" vs. "lazy". The former is in reference to the denotational semantics, whereas the latter characterizes the operational semantics.
mietek · 2014-05-03
Haskell is great for DSLs. Some loose thoughts:
- 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…
anon1385 · 2013-11-30
It doesn't seem that meaningful to compare a totally naive C implementation to an optimised Haskell one either. (Well, other than to show how fast C is even without any effort to optimise the code). Saying you have to keep the algorithm the same seems like a rather arbitrary limitation on the comparisons, especially since some algorithms are much less of a natural fit in some languages (see: quicksort in Haskell vs C [1]).
I would suggest it's best to show (at least) 4 versions of the code to compare two language: the naive implementation in both languages, and the really optimised version in both languages (plus intermediate levels of optimisation if you feel dedicated). That gives a picture of how fast the typical code one would write will be, as well as the potential for optimisation if you are experiencing bottlenecks, and how much effort it takes to optimise the code.
[1] http://augustss.blogspot.co.uk/2007/08/quicksort-in-haskell-quicksort-…
andolanra · 2013-02-22
Laziness (or, properly, non-strictness) enables a radically different style of programming, and combined with functional purity, also enables kinds of code transformation that are not valid in strict, effectful languages [1]. Almost any dynamic programming algorithm is trivial in Haskell, c.f. packrat parsing, which is embarrassingly easy to implement using a table of lazy values, and you can also trivially write control structures and infinite data structures [2].
The big problem is that reasoning about non-strict evaluation is quite non-intuitive (although not impossible.) It's quite easy to write code which seems inefficient that runs in no time at all, and equally easy to write code that seems efficient that takes a long time to run. It requires a rough understanding of how your compiler is optimizing your program and what the resulting code is doing, which can be tricky. Laziness also (not surprisingly) interacts with side-effects in a complicated way, so much work has been done to alleviate the problems with lazy IO, e.g. iteratees [3].
So, yes, sometimes it's a great thing, and sometimes it's a problem. The position of the Haskell community is that the exploration of how to properly leverage laziness is worth the tradeoff, but there is indeed a tradeoff.
[1]: http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-i…
[2]: Infinite data structures (i.e. codata) can be written/created in a strict language, but the ability to write them falls out of…
ddellacosta · 2025-12-16
This is not a direct response to the question of how laziness obviates the need for macros, but it mentions some specific relevant cases:
https://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-…
mafm · 2023-07-09
This looks nice. Looking forward to going through it and the related earlier stuff carefully at leisure.
I'm sure the author is well aware, but Lennart Augustsson wrote a really nice blog post responding to the original "Simply Easy!" in 2007 that was a lot more fun and simple than the "Simply Easy" paper.
http://augustss.blogspot.com/2007/10/simpler-easier-in-recent-paper-si…
ghostwriter · 2022-12-06
> If you take Haskell and remove all the types (e.g. Scheme or JavaScript), you can have all the same abstractions, with basically the same syntax and operational behavior.
This isn't generally true, as such a language would have to be lazy by default and the property is more important than having all the types, because certain abstractions that can be expressed "naturally" in Haskell is a byproduct of non-strict semantics. Also it's the property that sometimes helps avoiding worst-case complexity of evaluations - something that eager languages have to live with at all times, no matter the abstractions.
There's a few examples here: https://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-…
nequo · 2022-08-28
There is the argument that lazy evaluation improves composability and thus code reuse.[1] Edward Kmett also described how he uses laziness on Reddit sometime ago.[2]
[1] http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-i…
[2] https://www.reddit.com/r/haskell/comments/l98v73/comment/glgun65/
tome · 2019-10-06
Aha, yes! You are right. But then so does strictness. See https://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-… for some examples.
Laziness is a definitely a double-edged sword, with sharp edges.
omaranto · 2018-08-14
Lennart Augustsson implemented a JIT for BASIC as an EDSL in Haskell using LLVM.
A blog post he wrote about it: http://augustss.blogspot.com/2009/02/more-basic-not-that-anybody-shoul…
The JIT itself: https://hackage.haskell.org/package/BASIC
louthy · 2017-05-19
How about BASIC in Haskell?
http://augustss.blogspot.co.uk/search/label/BASIC
chubot · 2017-05-02
Eh, I'm pretty sure that suffers from the problem noted here:
https://news.ycombinator.com/item?id=13375108
See the "genuine sieve of eratosthenes" paper, and also:
http://augustss.blogspot.com/2007/08/quicksort-in-haskell-quicksort-is…
sclv · 2016-08-02
This is an interesting question. As much more of a Haskeller than an MLer I don't tend to feel the "need" to structure my programs explicitly modularly, and when I do I sort of instinctively use a combination of typeclasses and polymorphic higher-order functions to do so.
More basically, just think "everywhere I would open a module, instead I can take a parameterized record of functions" (and furthermore, if a datatype uniquely determines that record, I can associate a typeclass to that datatype). There are limitations to this, but in fewer circumstances than you'd think -- mainly about sort of cross-modularity (aka the expression problem).
There was a very nice discussion on lennart's blog about this in 2008, with a problem posed and some partial solutions (read bottom post to top):
http://augustss.blogspot.com/2008_12_01_archive.html
wz1000 · 2015-06-21
Here's a version in Haskell implemented using a monadic DSL: http://augustss.blogspot.in/2009/02/more-basic-not-that-anybody-should…
Also, here's ASM embedded in Haskell: http://wall.org/~lewis/2013/10/15/asm-monad.html
berdario · 2015-02-19
Facebook is also creating tools with Haskell:
https://github.com/facebook/Haxl
My 2 cents: definitely _also_ learn OCaml down the line. But:
- my pet peeve with OCaml is the lack of a builtin type for Unicode strings (the only other language still commonly used with this shortcoming is PHP), and this could be an issue if you plan to write some web app code that needs to be internationalized
- OCaml is strict, Haskell is one of the very few languages that is non-strict: aside from the didactic purpose of exposing yoursefl to something different, that's a feature that can help reasoning about what your code is doing:
http://augustss.blogspot.co.uk/2011/05/more-points-for-lazy-evaluation…
(then again, there're obviously downsides to non-strictness, and you might decide down the line that you prefer to write strict code in production... but it's good to know the alternatives)
thu · 2015-01-29
Lazy vs strict evaluation: Lennart, the author of the Mu compiler, has written about it: http://augustss.blogspot.co.uk/2011/05/more-points-for-lazy-evaluation…
SilasX · 2015-01-18
Hold on: does Haskell allow "the" QuickSort on one line, or just a sort? Because from what I've read, if you want to make Haskell do all the efficient stuff in a QS, you have to tell it a lot more, bloating the program.
Edit: this is what I had in mind: http://augustss.blogspot.com/2007/08/quicksort-in-haskell-quicksort-is…
Btw, I took AP Compsci with C++ in Austin around that time, so we might know each other.
tikhonj · 2013-01-30
Your last complaint is not fundamental to the language: it's just a matter of library design. I guess Haskellers don't like state very much in any guise, so having awkward syntax for it is only natural. Both programs are fundamentally ugly, so having it be superficially ugly as well is no big loss.
However, if you really wanted to, you could have almost C-like syntax[1]. The demo in that particular blog post has its own issues, but there is no fundamental reason why you couldn't apply some of those ideas to the normal ST API. I suspect that people simply don't care enough.
[1]: http://augustss.blogspot.co.il/2007/08/programming-in-c-ummm-haskell-h…
rpearl · 2012-11-25
http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-i… is a very good discussion of why laziness has some nice semantic properties from the theory point of view.
And the post it is responding to, https://existentialtype.wordpress.com/2011/04/24/the-real-point-of-laz… makes some interesting points against it as well.
dons · 2011-06-11
Haskell is the only widely used language that uses lazy evaluation by default. This has historically lead to confusion and difficulties with reasoning about time and space, particularly when a programmer is coming from a strict language.
Why do we care about laziness by default? Like purity, it adds power and expressiveness.
----
Finally, what would a strict Haskell be like? Here's a discussion: http://augustss.blogspot.com/2011/05/more-points-for-lazy-evaluation-i… )
danieldk · 2011-06-04
But the 'canonical quicksort' is not quicksort ;), just a slow look-alike:
http://augustss.blogspot.com/2007/08/quicksort-in-haskell-quicksort-is…