> Your still missing the point.
No, I'm not missing the point.
> Your example shows a simple hello world and doesn't speak to the point being made.
Hmm... Let's do an analysis:
* My example demonstrates reading from a given file descriptor (FD 0 -- stdin -- in this case), and that reading happens asynchronously (as I had pointed out, and even provided white papers describing how this works). Again, this is despite the syntax looking like a naive, synchronous program. The GHC Run Time System handles asynchronously reading from the FD and scheduling threads as appropriate such that OS threads aren't tied up waiting on what would otherwise be a synchronous read(2).
* As a bonus, it also demonstrates writing to standard out.
Now, one could take exception to the fact that my example doesn't give any evidence that similar asynchrony should be expected in a web stack. One would be wrong: as anyone with, say, as little as a year of experience writing web applications on POSIX systems should know, the Berkeley sockets API exposes sockets as file descriptors, so the same generic async event handling system in GHC's RTS applies equally well to networked IO. GHC and Node (via libuv) uses similar primitive kernel APIs at the end of the day, the only difference being that Haskell doesn't require that you reify the callbacks in the source language.
Idiomatic? Check.
By default? Check.
So no, I think I do get the point, but if you still disagree, I'm all ears.
If my tone sounds harsh, it's because I spent the time to provide links to two papers and even gave a small example of what the syntax would look like for a minimal program that demonstrates IO. In turn, you're telling me that I'm missing the point. I would argue that, if you read either of those two papers, and you knew about the implications with respect to networked IO (if you didn't, you could easily research the Berkeley sockets API, kqueue(2), poll(2), etc -- all mentioned in the papers), you would see what I'm getting at with my example code and the papers referenced. I can only posit that you haven't read the papers, or if you did, you must have not done so in earnest. Hopefully you can see how I would be frustrated when I've put in time to research this space, and when I share something, I'm met with what (in appearance) amounts to a dissimilar level of diligence and, ultimately, an empty dismissal.
If something else is going on, I would be more than happy to issue an apology.
> I am sure you can get a more relevant example going in Scotty, but it appears that it didn't show up until 2012.
Open source web frameworks for Haskell go back to (at least as far as) 2009.
Happstack: (2009): https://hackage.haskell.org/package/happstack-server-0.1
Yesod (2010): https://hackage.haskell.org/package/yesod-0.0.0
Snap (2010): https://hackage.haskell.org/package/snap-0.3.0
I didn't provide a "hello world"-like example of a web app because my command-line example only requires a trivial inference on the part of the reader to realize that the same asynchronous treatment of FDs there applies equally well to sockets, and thus web app programming in general; I deemed a full fledged web app example as more complicated than necessary to get my point across.
For what it's worth, here's an example in Happstack, straight from the documentation:
module Main where
import Happstack.Server (nullConf, simpleHTTP, toResponse, ok)
main :: IO ()
main = simpleHTTP nullConf $ ok "Hello, World!"
And ...
$ curl http://localhost:8000/
Hello, World!
Also, a note on tense:
> It's that you could quickly write web services idomatically that did so by default.
I wasn't questioning the rationale for using Node back in 2009. My point is this: eight years have passed since Node was released, and alternative solutions have since been released. Somehow the Node community (and the greater web dev community in general) are oblivious to these alternative approaches.
I suspect this is because most web devs see the callbacks as evidence that IO is asynchronous in Node, and at the same time lack the requisite experience to intuit how another language might implement asynchronous IO while providing a syntax that looks like the usual synchronous model. Now, they could actually read the research papers put out, but they don't, and so everyone keeps going on about the technological revolution that is Node and its approach to IO, oblivious to alternative solutions that (arguably) provide a more convenient programming model (and is, if we throw in support for multiple threads, more computationally powerful, too).
Such laziness and/or lack of curiosity is pervasive in the industry, and that's frustrating.