Bryan O'Sullivan writes about Haskell, covering parsers, benchmarking with Criterion, performance, and book reviews.
HN commenters cite it as a great blog showing how fast Haskell can be, including a bug-hunting post and his concurrent Haskell book.
The OP's argument that fork doesn't make a lot of sense for what it gets used for seems persuasive, I'm definitely curious how it ended up that way. This was relatively early days for multi-tasking (ie "time-sharing") at all, maybe the only explanation is that it was early days and it wasn't clear how it was going to end up being used and 'fork' was convenient to implement. Or that's how the previous time-sharing OSs did it, for equally mysterious reasons, and it was copied? I dunno.
The suggestion that it was done this way because the expected main use case was a fork without an exec at least provides a rational explanation (I don't think 'threads' as distinct from processes existed yet in unix? a fork without an exec was the closest thing you had), but I have no idea if it's historically accurate. Would be interesting to find people who were around and get some background.
Ah, this is interesting:
> Then came Unix, in the early 1970s. The Unix notion of a “process” became a sequential thread of control plus a virtual address space (incidentally, the Unix notion of a process derived directly from the Multics process design [Saltzer, 66]). So “processes”, in the Unix sense, are quite heavyweight machines. Since they cannot share memory (each has its own address space), they interact through pipes, signals, etc). Shared memory (also a rather ponderous mechanism) was added much later.
> After some time, Unix users started to miss the old processes that could share memory.…
> They're not that bad (GNU coreutils is generally pretty good) and you usually remember the edge cases fairly quickly (eg `dd`). Sadly you get inconsistencies in all coding frameworks, whether it's semantic, function names in the core libraries or whatever.
Generally this is all awful and low-level. Just see the UI interface difference between 'dd' and 'Copy File' on a Lisp Machine. The UI is worlds away.
> UNIX shells do have a lot of hidden gotchya's which can make life "interesting" (read: "oh fuck oh fuck oh fuck" lol). But the power of being able to use reusable blocks of any language through pipelining (and to a lesser extent, exit codes) is genius. It means one can mix and match LISP, Java, Perl, Python, C++, Go all inside one shell script.
You can do that on a Lisp Machine, too. With the difference that no pipelining of text is necessary. Just reuse the objects. The data is all fully object-oriented and self identifying.
Note that I'm using Unix and other OS variants since the 80s and I'm fully aware of command line UIs from VMS, SUN OS, Cisco, IBM AIX, OSX, GNU, Plan9, Oberon OS, and various others.
> I do understand the hate towards UNIX shells.
It's not hate. Most Unix shells are just fully dumb. Many people like to use primitive text based UIs with lots of corner cases, which makes them look intelligent for remembering obscure commands, obscure options without real UI help.
Take cp.
The shell does not know the various options the command takes. The shell…
Simple does not imply easy. As an extreme example, a unicycle is simpler than a bicycle--fewer components, simpler structure, no gearing--but also more difficult to learn.
Really, I'll just have to point you to the "Simple Made Easy" talk again. The core point being that there's a difference between something being "simple" and something being "easy", and we should generally strive for the former rather than the latter.
Having a deep theoretical foundation is also not a sign of complexity. Instead, like most of math, it's usually a sign of simplicity. After all, math always strives for elegance and simplicity.
What it means is that a lot of smart people have spent a lot of time thinking things through using a strict framework for reasoning that ensures everything is consistent. The theoretical framework lets us simplify by recasting different concepts using the same fundamental ideas. If we can capture things like state, errors and non-determinism using a single concept, we've made things simpler because now we have a common ground and relationship between seemingly disjoint ideas. This is exactly what Haskell (and the theory behind it) does.
This theoretical foundation, coupled with the relative simplicity and consistency of the language, actually make code much easier to reason about in Haskell than in other languages, except for some performance issues. Basically, as long as your main concern is in semantics--and, for 90% of your code, it is--Haskell makes life easier…
Thanks for the comments and encouragement, it really helps a lot!
What you describe is precisely what we've aimed at the whole time, but there is a reasonable amount of work that the absolute beginner has to get through before one can tackle anything at that level. The work we've done so far is about as real world as a beginner could hope for, we think. Mind you, up to section 8 pretty much has to be toyish programs of a few lines of code so as not to bamboozle the reader, because they know very little up to there. These sections are tiny for that reason - to keep them interested.
We're slowly releasing the sections for free. Just released another one today (Section 8). It won't be until Section 9 that we start to encounter programs that one could see how they might be truly useful if more work was done on them.
Finding all the movies in your movie collection that start with a letter in the first half of the alphabet is pretty toy, for example (in Section 9) :) - that's the next section we'll release for free on the site. However, we can start to see how that could easily become something useful - like maybe a DVD collection manager database kind of thing, with a bit more coding.
Then, when at around Section 17, we know enough Haskell to be able to read small, but real programs: a times-table "game", and a tiny adventure game (it only has 2 rooms). These are trivial non-real programs from a real-world perspective, but they contain a lot of the elements needed for real…
> What does Haskell have? It has Req (and a bunch of other also rans), and the docs for Req are atrocious, spanning a staggering 1 (one) example and then a meandering essay on the deficiency of other Haskell HTTP clients. It's not good enough.
For HTTP request library, most would recommend Wreq. Being most popular, the documentation is really good I might say with most used API have their own example [1]. You can also easily find great tutorial on the net, like http://www.serpentine.com/wreq/tutorial.html for example. Honestly I never use Req myself and looking at the documentation myself, even though I don't it's lacking, I think it's not really geared toward Haskell beginners so maybe you have a point there.
As a novice Haskell programer who only use it for side projects, I don't think the documentation is that bad and it's only getting better. Most popular libraries like database clients and web frameworks have intensive documentation and tutorial nowadays.
I agree with you for the state of IDE support, it leaves something to be desired. But people are still working on it[2]. For now I mostly use vim with help of linter and formatter. The great thing about good type system is, you can still do much even without great IDE support. Haskell already have working and great REPL support that make development a breeze so it helped. I'll still take Haskell over OCaml or Scala anyday. Rust is great and I love it so much that it's my go to language for something system…
Some context: http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/
It probably marks the end of the quest to find the unconditionally correct and fast algorithm to print floating point numbers. The prior state of the art, Grisu3 (2010), is great but is only fast for 99.5% of inputs; it was nevertheless so useful that there are now several language implementations with Grisu3 (IIRC, including V8, SpiderMonkey, Go, Julia and Rust). The new algorithm, Errol3, improves Grisu3 by using double-double floating point format (instead of 64-bit custom FP) and applying more precise error analysis.
Quoting the highlight of the paper: (emphases original)
> After removing the narrowing and widening steps, we used the enumeration algorithm to generate a list of possibly incorrect or suboptimal inputs. Each input was run using Errol2 to enumerate a complete list of inputs that do not generate correct and optimal outputs. In total, we found that only 45 inputs (of the nearly 2^64 inputs) generate incorrect or suboptimal results; all other inputs are guaranteed to generete correct and optimal output. In order to correctly and optimally handle the failing inputs, they are hard-coded into a lookup table that maps the failing inputs to correct and optimal outputs. Combining the special handling of integers and this lookup table, Errol3 is guaranteed to be correct and optimal without runtime checks.