Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> No, this is just not true, are we using the same JavaScript? JavaScript's functions change only based on modified application state, not on any other side effect.

If you read some file (or remote URL) multiple times, you may get different data each time. Haskell makes "functions" with this property clearly distinct from regular functions. Most languages, including JavaScript, don't. That's what matters, not whether I/O is synchronous or not.

> Sure, in the current Haskell that's true. In previous iterations of Haskell this wasn't always the case though

That may or may not be technically true but it's not really informative or relevant - Haskell has had monadic I/O for over 20 years and the overwhelming majority of Haskell users have never used any other kind.



> If you read some file (or remote URL) multiple times, you may get different data each time.

True, but just like in Haskell that data is not returned by the function, JavaScript functions are pure for I/O.


Well, either it's impossible to read a file (or remote URL) in JavaScript, or the data gets into your program somehow. Whether you get it as a plain value, a promise, or a callback is not really relevant; it comes into your program looking like a normal, idiomatic function evaluation (because passing callbacks to normal functions like Array.map is perfectly idiomatic JavaScript). There is no practical way to separate a JavaScript program into fragments that depend on external mutable state (files, remote services) and fragments that don't, because a function that accesses and depends on external mutable state (say, a calculation that uses a lookup table that it loads from a file) looks the same, at API level, as one that doesn't.


Well that's true. I do think there's some value to the fact that if you call a JavaScript function you are guaranteed that no I/O has been executed (provided no on is using the old sync API's) before the function returned. I lean on this property often, and I don't know any other language besides Haskell that has this property.

I do agree that Haskell is even stronger because it doesn't just guarantee the I/O has not yet been executed yet, it also reveals the intent of I/O through the use of the I/O monad.


> I do think there's some value to the fact that if you call a JavaScript function you are guaranteed that no I/O has been executed (provided no on is using the old sync API's) before the function returned. I lean on this property often, and I don't know any other language besides Haskell that has this property.

Are you just talking about the absence of shared-memory threading (which you also get in, say, OCaml, or even Erlang or idiomatic Python)? I can understand the value of not having to reason about arbitrarily interleaved executions, but not how that particular kind of sequencing of I/O specifically is more useful than that.


What do you mean "the function"? One can certainly write functions in JavaScript that return the result of an HTTP request, and that result can change each time the function is run. In Haskell you can't do that.


You can't do that in idiomatic JavaScript, at least I've never done such a thing in the past 15 years. Maybe you could share an example to show me?


Sure, synchronous XHTMLHttpRequest.send() is an example

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequ...

Certainly it's not idiomatic but that's not lmm's point. The point is that it's possible. In Haskell it's not possible.


Sure it's possible, you can use unsafePerformIO just fine in Haskell. It's idiomatic to not use it, just like it's idiomatic to not use synchronous I/O in JavaScript. Imo it's also not really interesting to talk about non idiomatic use of a language but I guess we disagree there.


It seems to me that there is a qualitative difference between having synchronous HTTP requests in the JavaScript standard library and having access to System.IO.Unsafe.unsafePerformIO in Haskell. Still, I take your point that in theory JavaScript could remove all synchronous I/O side effecting functions and replace them with continuation-based ones.

Anyway, we've wandered pretty far off the main thread, which wasn't mine to begin with, so I'll let lmm take up the discussion again if he wants.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: